summaryrefslogtreecommitdiffstats
path: root/Objects/enumobject.c
blob: f69a002a2ce673e3569dffbc361d5a026499f4f9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/* enumerate object */

#include "Python.h"

typedef struct {
	PyObject_HEAD
	long      en_index;        /* current index of enumeration */
	PyObject* en_sit;          /* secondary iterator of enumeration */
} enumobject;

PyTypeObject PyEnum_Type;

static PyObject *
enum_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
	enumobject *en;
	PyObject *seq = NULL;
	static char *kwlist[] = {"sequence", 0};

	if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:enumerate", kwlist,
					 &seq))
		return NULL;

	en = (enumobject *)type->tp_alloc(type, 0);
	if (en == NULL)
		return NULL;
	en->en_index = 0;
	en->en_sit = PyObject_GetIter(seq);
	if (en->en_sit == NULL) {
		Py_DECREF(en);
		return NULL;
	}
	return (PyObject *)en;
}

static void
enum_dealloc(enumobject *en)
{
	PyObject_GC_UnTrack(en);
	Py_XDECREF(en->en_sit);
	en->ob_type->tp_free(en);
}

static int
enum_traverse(enumobject *en, visitproc visit, void *arg)
{
	if (en->en_sit)
		return visit(en->en_sit, arg);
	return 0;
}

static PyObject *
enum_next(enumobject *en)
{
	PyObject *result;
	PyObject *next_index;
	PyObject *next_item;

	result = PyTuple_New(2);
	if (result == NULL)
		return NULL;

	next_index = PyInt_FromLong(en->en_index);
	if (next_index == NULL) {
		Py_DECREF(result);
		return NULL;
	}
	PyTuple_SET_ITEM(result, 0, next_index);

	next_item = PyIter_Next(en->en_sit);
	if (next_item == NULL) {
		Py_DECREF(result);
		return NULL;
	}

	en->en_index++;
	PyTuple_SET_ITEM(result, 1, next_item);
	return result;
}

static PyObject *
enum_getiter(PyObject *en)
{
	Py_INCREF(en);
	return en;
}

PyDoc_STRVAR(enum_doc,
"enumerate(iterable) -> create an enumerating-iterator");

PyTypeObject PyEnum_Type = {
	PyObject_HEAD_INIT(&PyType_Type)
	0,                              /* ob_size */
	"enumerate",                    /* tp_name */
	sizeof(enumobject),             /* tp_basicsize */
	0,                              /* tp_itemsize */
	/* methods */
	(destructor)enum_dealloc,       /* tp_dealloc */
	0,                              /* tp_print */
	0,                              /* tp_getattr */
	0,                              /* tp_setattr */
	0,                              /* tp_compare */
	0,                              /* tp_repr */
	0,                              /* tp_as_number */
	0,                              /* tp_as_sequence */
	0,                              /* tp_as_mapping */
	0,                              /* tp_hash */
	0,                              /* tp_call */
	0,                              /* tp_str */
	PyObject_GenericGetAttr,        /* tp_getattro */
	0,                              /* tp_setattro */
	0,                              /* tp_as_buffer */
	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
		Py_TPFLAGS_BASETYPE,    /* tp_flags */
	enum_doc,                       /* tp_doc */
	(traverseproc)enum_traverse,    /* tp_traverse */
	0,                              /* tp_clear */
	0,                              /* tp_richcompare */
	0,                              /* tp_weaklistoffset */
	(getiterfunc)enum_getiter,      /* tp_iter */
	(iternextfunc)enum_next,        /* tp_iternext */
	0,                              /* tp_methods */
	0,                              /* tp_members */
	0,                              /* tp_getset */
	0,                              /* tp_base */
	0,                              /* tp_dict */
	0,                              /* tp_descr_get */
	0,                              /* tp_descr_set */
	0,                              /* tp_dictoffset */
	0,                              /* tp_init */
	PyType_GenericAlloc,            /* tp_alloc */
	enum_new,                       /* tp_new */
	PyObject_GC_Del,                /* tp_free */
};
t) = 0; + virtual void insertItem(QGraphicsItem *item) = 0; + virtual void insertItems(QList items) = 0; + virtual void removeItem(QGraphicsItem *item) = 0; + virtual void removeItems(QList items) = 0; virtual QList items(const QRectF &rect) = 0; -- cgit v0.12 From e2e30d5c0ca99a47cc142465436d5e0a3f616b82 Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Tue, 7 Apr 2009 20:06:38 +0200 Subject: Fixes: Make the bsp tree inherits from the new API --- src/gui/graphicsview/qgraphicsscene.cpp | 6 +++--- src/gui/graphicsview/qgraphicsscene_bsp.cpp | 31 ++++++++++++++++++++++------- src/gui/graphicsview/qgraphicsscene_bsp_p.h | 16 ++++++++++----- src/gui/graphicsview/qgraphicsscene_p.h | 2 +- src/gui/graphicsview/qgraphicssceneindex.h | 4 ++-- 5 files changed, 41 insertions(+), 18 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index a41f931..8660853 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -443,7 +443,7 @@ void QGraphicsScenePrivate::addToIndex(QGraphicsItem *item) { if (indexMethod == QGraphicsScene::BspTreeIndex) { if (item->d_func()->index != -1) { - bspTree.insertItem(item, item->sceneBoundingRect()); + bspTree.insertItem(item); foreach (QGraphicsItem *child, item->children()) child->addToIndex(); } else { @@ -472,7 +472,7 @@ void QGraphicsScenePrivate::removeFromIndex(QGraphicsItem *item) if (indexMethod == QGraphicsScene::CustomIndex) customIndex->removeItem(item); else - bspTree.removeItem(item, item->sceneBoundingRect()); + bspTree.removeItem(item); freeItemIndexes << index; indexedItems[index] = 0; item->d_func()->index = -1; @@ -579,7 +579,7 @@ void QGraphicsScenePrivate::_q_updateIndex() if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) continue; if (indexMethod == QGraphicsScene::BspTreeIndex) - bspTree.insertItem(item, rect); + bspTree.insertItem(item); if (indexMethod == QGraphicsScene::CustomIndex) customIndex->insertItem(item); diff --git a/src/gui/graphicsview/qgraphicsscene_bsp.cpp b/src/gui/graphicsview/qgraphicsscene_bsp.cpp index f8fa450..c295cb3 100644 --- a/src/gui/graphicsview/qgraphicsscene_bsp.cpp +++ b/src/gui/graphicsview/qgraphicsscene_bsp.cpp @@ -100,7 +100,7 @@ QGraphicsSceneBspTree::~QGraphicsSceneBspTree() void QGraphicsSceneBspTree::initialize(const QRectF &rect, int depth) { - this->rect = rect; + sceneRect = rect; leafCnt = 0; nodes.resize((1 << (depth + 1)) - 1); nodes.fill(Node()); @@ -117,19 +117,36 @@ void QGraphicsSceneBspTree::clear() leaves.clear(); } -void QGraphicsSceneBspTree::insertItem(QGraphicsItem *item, const QRectF &rect) +QRectF QGraphicsSceneBspTree::rect() const +{ + return sceneRect; +} + +void QGraphicsSceneBspTree::setRect(const QRectF &rect) +{ + sceneRect = rect; +} + +void QGraphicsSceneBspTree::insertItem(QGraphicsItem *item) { insertVisitor->item = item; - climbTree(insertVisitor, rect); + climbTree(insertVisitor, item->sceneBoundingRect()); +} + +void QGraphicsSceneBspTree::insertItems(const QList &items) +{ + foreach(QGraphicsItem *item, items) { + insertItem(item); + } } -void QGraphicsSceneBspTree::removeItem(QGraphicsItem *item, const QRectF &rect) +void QGraphicsSceneBspTree::removeItem(QGraphicsItem *item) { removeVisitor->item = item; - climbTree(removeVisitor, rect); + climbTree(removeVisitor, item->sceneBoundingRect()); } -void QGraphicsSceneBspTree::removeItems(const QSet &items) +void QGraphicsSceneBspTree::removeItems(const QList &items) { for (int i = 0; i < leaves.size(); ++i) { QList newItemList; @@ -302,7 +319,7 @@ void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, con QRectF QGraphicsSceneBspTree::rectForIndex(int index) const { if (index <= 0) - return rect; + return sceneRect; int parentIdx = parentIndex(index); QRectF rect = rectForIndex(parentIdx); diff --git a/src/gui/graphicsview/qgraphicsscene_bsp_p.h b/src/gui/graphicsview/qgraphicsscene_bsp_p.h index e6ceb78..4114b3b 100644 --- a/src/gui/graphicsview/qgraphicsscene_bsp_p.h +++ b/src/gui/graphicsview/qgraphicsscene_bsp_p.h @@ -60,6 +60,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -69,7 +70,7 @@ class QGraphicsSceneInsertItemBspTreeVisitor; class QGraphicsSceneRemoveItemBspTreeVisitor; class QGraphicsSceneFindItemBspTreeVisitor; -class QGraphicsSceneBspTree +class QGraphicsSceneBspTree : public QGraphicsSceneIndex { public: struct Node @@ -87,10 +88,13 @@ public: void initialize(const QRectF &rect, int depth); void clear(); + QRectF rect() const; + void setRect(const QRectF &rect); - void insertItem(QGraphicsItem *item, const QRectF &rect); - void removeItem(QGraphicsItem *item, const QRectF &rect); - void removeItems(const QSet &items); + void insertItem(QGraphicsItem *item); + void insertItems(const QList &items); + void removeItem(QGraphicsItem *item); + void removeItems(const QList &items); QList items(const QRectF &rect); QList items(const QPointF &pos); @@ -116,7 +120,7 @@ private: QVector nodes; QVector > leaves; int leafCnt; - QRectF rect; + QRectF sceneRect; QGraphicsSceneInsertItemBspTreeVisitor *insertVisitor; QGraphicsSceneRemoveItemBspTreeVisitor *removeVisitor; @@ -130,6 +134,8 @@ public: virtual void visit(QList *items) = 0; }; +Q_DECLARE_TYPEINFO(QGraphicsSceneBspTree::Node, Q_PRIMITIVE_TYPE); + QT_END_NAMESPACE #endif // QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index fe36fbd..aacbc40 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -132,7 +132,7 @@ public: bool purgePending; void _q_removeItemLater(QGraphicsItem *item); - QSet removedItems; + QList removedItems; void purgeRemovedItems(); QBrush backgroundBrush; diff --git a/src/gui/graphicsview/qgraphicssceneindex.h b/src/gui/graphicsview/qgraphicssceneindex.h index 5e825ba..bda6f5e 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.h +++ b/src/gui/graphicsview/qgraphicssceneindex.h @@ -69,9 +69,9 @@ public: virtual void clear() = 0; virtual void insertItem(QGraphicsItem *item) = 0; - virtual void insertItems(QList items) = 0; + virtual void insertItems(const QList &items) = 0; virtual void removeItem(QGraphicsItem *item) = 0; - virtual void removeItems(QList items) = 0; + virtual void removeItems(const QList &items) = 0; virtual QList items(const QRectF &rect) = 0; -- cgit v0.12 From 45c70c9834316f39a939b87450099560fd286a6e Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Tue, 7 Apr 2009 20:11:32 +0200 Subject: Fixes: Default implementation for QGraphicsSceneIndex::removeItems and QGraphicsSceneIndex::insertItems --- src/gui/graphicsview/qgraphicsscene_bsp.cpp | 7 ------- src/gui/graphicsview/qgraphicsscene_bsp_p.h | 1 - src/gui/graphicsview/qgraphicssceneindex.cpp | 13 +++++++++++++ src/gui/graphicsview/qgraphicssceneindex.h | 5 +++-- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene_bsp.cpp b/src/gui/graphicsview/qgraphicsscene_bsp.cpp index c295cb3..bf95893 100644 --- a/src/gui/graphicsview/qgraphicsscene_bsp.cpp +++ b/src/gui/graphicsview/qgraphicsscene_bsp.cpp @@ -133,13 +133,6 @@ void QGraphicsSceneBspTree::insertItem(QGraphicsItem *item) climbTree(insertVisitor, item->sceneBoundingRect()); } -void QGraphicsSceneBspTree::insertItems(const QList &items) -{ - foreach(QGraphicsItem *item, items) { - insertItem(item); - } -} - void QGraphicsSceneBspTree::removeItem(QGraphicsItem *item) { removeVisitor->item = item; diff --git a/src/gui/graphicsview/qgraphicsscene_bsp_p.h b/src/gui/graphicsview/qgraphicsscene_bsp_p.h index 4114b3b..a35148c 100644 --- a/src/gui/graphicsview/qgraphicsscene_bsp_p.h +++ b/src/gui/graphicsview/qgraphicsscene_bsp_p.h @@ -92,7 +92,6 @@ public: void setRect(const QRectF &rect); void insertItem(QGraphicsItem *item); - void insertItems(const QList &items); void removeItem(QGraphicsItem *item); void removeItems(const QList &items); diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index 7868388..d8c28ed 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -60,6 +60,19 @@ QGraphicsScene* QGraphicsSceneIndex::scene() return mscene; } +void QGraphicsSceneIndex::insertItems(const QList &items) +{ + foreach (QGraphicsItem *item, items) + insertItem(item); +} + +void QGraphicsSceneIndex::removeItems(const QList &items) +{ + foreach (QGraphicsItem *item, items) + removeItem(item); +} + + QT_END_NAMESPACE //#include "moc_qgraphicssceneindex.cpp" diff --git a/src/gui/graphicsview/qgraphicssceneindex.h b/src/gui/graphicsview/qgraphicssceneindex.h index bda6f5e..df398ae 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.h +++ b/src/gui/graphicsview/qgraphicssceneindex.h @@ -69,9 +69,10 @@ public: virtual void clear() = 0; virtual void insertItem(QGraphicsItem *item) = 0; - virtual void insertItems(const QList &items) = 0; virtual void removeItem(QGraphicsItem *item) = 0; - virtual void removeItems(const QList &items) = 0; + + virtual void insertItems(const QList &items); + virtual void removeItems(const QList &items); virtual QList items(const QRectF &rect) = 0; -- cgit v0.12 From 600beb2a2ed1c3df581230c526f1e64b78112477 Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Thu, 12 Mar 2009 16:08:24 +0100 Subject: Fixes: Mark the BSP tree class so we can autotest it. --- src/gui/graphicsview/qgraphicsscene_bsp_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsscene_bsp_p.h b/src/gui/graphicsview/qgraphicsscene_bsp_p.h index a35148c..ebcb402 100644 --- a/src/gui/graphicsview/qgraphicsscene_bsp_p.h +++ b/src/gui/graphicsview/qgraphicsscene_bsp_p.h @@ -70,7 +70,7 @@ class QGraphicsSceneInsertItemBspTreeVisitor; class QGraphicsSceneRemoveItemBspTreeVisitor; class QGraphicsSceneFindItemBspTreeVisitor; -class QGraphicsSceneBspTree : public QGraphicsSceneIndex +class Q_AUTOTEST_EXPORT QGraphicsSceneBspTree : public QGraphicsSceneIndex { public: struct Node -- cgit v0.12 From d5ab1562ea7b8ce8e94e8db9ea2a7fcab17f657f Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Thu, 12 Mar 2009 15:51:19 +0100 Subject: Fixes: Add a simple test for the scene index. Details: This is just the beginning. More complex tests follow. --- tests/auto/auto.pro | 1 + .../qgraphicssceneindex/qgraphicssceneindex.pro | 3 + .../tst_qgraphicssceneindex.cpp | 74 ++++++++++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 tests/auto/qgraphicssceneindex/qgraphicssceneindex.pro create mode 100644 tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index 443ee7e..9bde383 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -140,6 +140,7 @@ SUBDIRS += bic \ qgraphicsitem \ qgraphicsitemanimation \ qgraphicsscene \ + qgraphicssceneindex \ qgraphicsview \ qgridlayout \ qgroupbox \ diff --git a/tests/auto/qgraphicssceneindex/qgraphicssceneindex.pro b/tests/auto/qgraphicssceneindex/qgraphicssceneindex.pro new file mode 100644 index 0000000..740a23e --- /dev/null +++ b/tests/auto/qgraphicssceneindex/qgraphicssceneindex.pro @@ -0,0 +1,3 @@ +load(qttest_p4) +SOURCES += tst_qgraphicssceneindex.cpp + diff --git a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp new file mode 100644 index 0000000..209e4be --- /dev/null +++ b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include +#include +#include + +#include + +//TESTED_CLASS= +//TESTED_FILES= + +class tst_QGraphicsSceneIndex : public QObject +{ + Q_OBJECT +public slots: + void initTestCase(); + +private slots: + void sceneRect(); +}; + +void tst_QGraphicsSceneIndex::initTestCase() +{ +} + +void tst_QGraphicsSceneIndex::sceneRect() +{ + QGraphicsSceneIndex *index = new QGraphicsSceneBspTree; + index->setRect(QRectF(0, 0, 2000, 2000)); + QCOMPARE(index->rect(), QRectF(0, 0, 2000, 2000)); +} + +QTEST_MAIN(tst_QGraphicsSceneIndex) +#include "tst_qgraphicssceneindex.moc" -- cgit v0.12 From 14785a965fc475d220ca8592c6ee4a44a0be25f6 Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Mon, 16 Mar 2009 13:54:20 +0100 Subject: Fixes: Parametrize the test with potentially different indexing method. --- .../tst_qgraphicssceneindex.cpp | 28 +++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp index 209e4be..f2a2bf1 100644 --- a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp +++ b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp @@ -44,7 +44,6 @@ #include #include -#include //TESTED_CLASS= //TESTED_FILES= @@ -56,13 +55,40 @@ public slots: void initTestCase(); private slots: + void sceneRect_data(); void sceneRect(); + +private: + void common_data(); + QGraphicsSceneIndex *createIndex(const QString &name); }; void tst_QGraphicsSceneIndex::initTestCase() { } +void tst_QGraphicsSceneIndex::common_data() +{ + QTest::addColumn("indexMethod"); + + QTest::newRow("BSP") << QString("bsp"); +} + +QGraphicsSceneIndex *tst_QGraphicsSceneIndex::createIndex(const QString &indexMethod) +{ + QGraphicsSceneIndex *index = 0; + + if (indexMethod == "bsp") + index = new QGraphicsSceneBspTree; + + return index; +} + +void tst_QGraphicsSceneIndex::sceneRect_data() +{ + common_data(); +} + void tst_QGraphicsSceneIndex::sceneRect() { QGraphicsSceneIndex *index = new QGraphicsSceneBspTree; -- cgit v0.12 From 7b21055e3966ed8620586decaca4c30f9bf0823a Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Mon, 16 Mar 2009 13:57:05 +0100 Subject: Fixes: Autotest for changing the index method of a scene. --- .../qgraphicssceneindex/tst_qgraphicssceneindex.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp index f2a2bf1..9372823 100644 --- a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp +++ b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp @@ -41,6 +41,7 @@ #include +#include #include #include @@ -57,6 +58,8 @@ public slots: private slots: void sceneRect_data(); void sceneRect(); + void customIndex_data(); + void customIndex(); private: void common_data(); @@ -96,5 +99,23 @@ void tst_QGraphicsSceneIndex::sceneRect() QCOMPARE(index->rect(), QRectF(0, 0, 2000, 2000)); } +void tst_QGraphicsSceneIndex::customIndex_data() +{ + common_data(); +} + +void tst_QGraphicsSceneIndex::customIndex() +{ + QFETCH(QString, indexMethod); + QGraphicsSceneIndex *index = createIndex(indexMethod); + + QGraphicsScene scene; + scene.setSceneIndex(index); + + scene.addRect(0, 0, 30, 40); + QCOMPARE(scene.items(QRectF(0, 0, 10, 10)).count(), 1); +} + + QTEST_MAIN(tst_QGraphicsSceneIndex) #include "tst_qgraphicssceneindex.moc" -- cgit v0.12 From 7185361703e2837e4258b18350da791c84f7ef62 Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Mon, 16 Mar 2009 13:58:02 +0100 Subject: Fixes: Autotest for inserting non-overlapped items in the scene index. --- .../tst_qgraphicssceneindex.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp index 9372823..cfe3ef0 100644 --- a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp +++ b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp @@ -60,6 +60,8 @@ private slots: void sceneRect(); void customIndex_data(); void customIndex(); + void scatteredItems_data(); + void scatteredItems(); private: void common_data(); @@ -116,6 +118,26 @@ void tst_QGraphicsSceneIndex::customIndex() QCOMPARE(scene.items(QRectF(0, 0, 10, 10)).count(), 1); } +void tst_QGraphicsSceneIndex::scatteredItems_data() +{ + common_data(); +} + +void tst_QGraphicsSceneIndex::scatteredItems() +{ + QFETCH(QString, indexMethod); + QGraphicsSceneIndex *index = createIndex(indexMethod); + + QGraphicsScene scene; + scene.setSceneIndex(index); + + for (int i = 0; i < 10; ++i) + scene.addRect(i*50, i*50, 40, 35); + + QCOMPARE(scene.items(QRectF(0, 0, 10, 10)).count(), 1); + QCOMPARE(scene.items(QRectF(0, 0, 1000, 1000)).count(), 10); + QCOMPARE(scene.items(QRectF(-100, -1000, 0, 0)).count(), 0); +} QTEST_MAIN(tst_QGraphicsSceneIndex) #include "tst_qgraphicssceneindex.moc" -- cgit v0.12 From 2a1ced292424501d3bf453f337f8ce9c8c17bda9 Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Mon, 16 Mar 2009 15:07:06 +0100 Subject: Fixes: Initialize the BSP tree if it has not been initialized before. Details: The BSP tree internal to QGraphicsScene does need this as the scene does call initialize() at proper time. This fix is needed only for using the BSP tree as custom indexing and/or for autotest. --- src/gui/graphicsview/qgraphicsscene_bsp.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene_bsp.cpp b/src/gui/graphicsview/qgraphicsscene_bsp.cpp index bf95893..b73cba2 100644 --- a/src/gui/graphicsview/qgraphicsscene_bsp.cpp +++ b/src/gui/graphicsview/qgraphicsscene_bsp.cpp @@ -247,8 +247,10 @@ void QGraphicsSceneBspTree::initialize(const QRectF &rect, int depth, int index) void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QPointF &pos, int index) { - if (nodes.isEmpty()) - return; + if (nodes.isEmpty()) { + // should never happen for bsp tree internal to QGraphicsScene + initialize(sceneRect, 0); + } const Node &node = nodes.at(index); int childIndex = firstChildIndex(index); @@ -277,8 +279,10 @@ void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, con void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QRectF &rect, int index) { - if (nodes.isEmpty()) - return; + if (nodes.isEmpty()) { + // should never happen for bsp tree internal to QGraphicsScene + initialize(sceneRect, 0); + } const Node &node = nodes.at(index); int childIndex = firstChildIndex(index); -- cgit v0.12 From e30e12306c9cc834eada3ce07b32761748fa423a Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Mon, 16 Mar 2009 15:34:07 +0100 Subject: Fixes: Make some BSP tree functions as 'private'. --- src/gui/graphicsview/qgraphicsscene_bsp_p.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene_bsp_p.h b/src/gui/graphicsview/qgraphicsscene_bsp_p.h index ebcb402..a8c54f0 100644 --- a/src/gui/graphicsview/qgraphicsscene_bsp_p.h +++ b/src/gui/graphicsview/qgraphicsscene_bsp_p.h @@ -96,9 +96,13 @@ public: void removeItems(const QList &items); QList items(const QRectF &rect); - QList items(const QPointF &pos); + int leafCount() const; +private: + + QList items(const QPointF &pos); + inline int firstChildIndex(int index) const { return index * 2 + 1; } @@ -107,7 +111,6 @@ public: QString debug(int index) const; -private: void initialize(const QRectF &rect, int depth, int index); void climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QPointF &pos, int index = 0); void climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QRectF &rect, int index = 0); -- cgit v0.12 From 79257690c8fe8802e75a642138a2b466a0f54e65 Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Thu, 12 Mar 2009 15:43:19 +0100 Subject: Fixes: Added linear scene index class. Not used yet. --- src/gui/graphicsview/graphicsview.pri | 1 + src/gui/graphicsview/qgraphicsscene_linear_p.h | 110 +++++++++++++++++++++ .../tst_qgraphicssceneindex.cpp | 5 + 3 files changed, 116 insertions(+) create mode 100644 src/gui/graphicsview/qgraphicsscene_linear_p.h diff --git a/src/gui/graphicsview/graphicsview.pri b/src/gui/graphicsview/graphicsview.pri index f0bdddc..bc4d9dd 100644 --- a/src/gui/graphicsview/graphicsview.pri +++ b/src/gui/graphicsview/graphicsview.pri @@ -7,6 +7,7 @@ HEADERS += \ graphicsview/qgraphicsscene.h \ graphicsview/qgraphicsscene_p.h \ graphicsview/qgraphicsscene_bsp_p.h \ + graphicsview/qgraphicsscene_linear_p.h \ graphicsview/qgraphicssceneindex.h \ graphicsview/qgraphicssceneevent.h \ graphicsview/qgraphicsview_p.h \ diff --git a/src/gui/graphicsview/qgraphicsscene_linear_p.h b/src/gui/graphicsview/qgraphicsscene_linear_p.h new file mode 100644 index 0000000..1ef1902 --- /dev/null +++ b/src/gui/graphicsview/qgraphicsscene_linear_p.h @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGRAPHICSSCENELINEARINDEX_P_H +#define QGRAPHICSSCENELINEARINDEX_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + +#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class Q_AUTOTEST_EXPORT QGraphicsSceneLinearIndex : public QGraphicsSceneIndex +{ +private: + QRectF m_sceneRect; + QList m_items; + +public: + QGraphicsSceneLinearIndex(): QGraphicsSceneIndex() { + } + + virtual void setRect(const QRectF &rect) { + m_sceneRect = rect; + } + + virtual QRectF rect() const { + return m_sceneRect; + } + + virtual void clear() { + m_items.clear(); + } + + virtual void insertItem(QGraphicsItem *item) { + m_items << item; + } + + virtual void removeItem(QGraphicsItem *item) { + m_items.removeAll(item); + } + + virtual QList items(const QRectF &rect) { + QList result; + foreach (QGraphicsItem *item, m_items) + if (item->sceneBoundingRect().intersects(rect)) + result << item; + return result; + } +}; + +QT_END_NAMESPACE + +#endif // QT_NO_GRAPHICSVIEW + +#endif // QGRAPHICSSCENELINEARINDEX_P_H diff --git a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp index cfe3ef0..d199351 100644 --- a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp +++ b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp @@ -44,6 +44,7 @@ #include #include #include +#include //TESTED_CLASS= @@ -77,6 +78,7 @@ void tst_QGraphicsSceneIndex::common_data() QTest::addColumn("indexMethod"); QTest::newRow("BSP") << QString("bsp"); + QTest::newRow("Linear") << QString("linear"); } QGraphicsSceneIndex *tst_QGraphicsSceneIndex::createIndex(const QString &indexMethod) @@ -86,6 +88,9 @@ QGraphicsSceneIndex *tst_QGraphicsSceneIndex::createIndex(const QString &indexMe if (indexMethod == "bsp") index = new QGraphicsSceneBspTree; + if (indexMethod == "linear") + index = new QGraphicsSceneLinearIndex; + return index; } -- cgit v0.12 From ff2f96de0c71f53cc71902e8119c84aed9967226 Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Tue, 17 Mar 2009 12:06:44 +0100 Subject: Fixes: New updateItem(s) function with default implementation (of removing and inserting) --- src/gui/graphicsview/qgraphicssceneindex.cpp | 11 +++++++++++ src/gui/graphicsview/qgraphicssceneindex.h | 2 ++ 2 files changed, 13 insertions(+) diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index d8c28ed..cb84f6b 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -60,6 +60,12 @@ QGraphicsScene* QGraphicsSceneIndex::scene() return mscene; } +void QGraphicsSceneIndex::updateItem(QGraphicsItem *item) +{ + removeItem(item); + insertItem(item); +} + void QGraphicsSceneIndex::insertItems(const QList &items) { foreach (QGraphicsItem *item, items) @@ -72,6 +78,11 @@ void QGraphicsSceneIndex::removeItems(const QList &items) removeItem(item); } +void QGraphicsSceneIndex::updateItems(const QList &items) +{ + foreach (QGraphicsItem *item, items) + updateItem(item); +} QT_END_NAMESPACE diff --git a/src/gui/graphicsview/qgraphicssceneindex.h b/src/gui/graphicsview/qgraphicssceneindex.h index df398ae..6246753 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.h +++ b/src/gui/graphicsview/qgraphicssceneindex.h @@ -70,9 +70,11 @@ public: virtual void insertItem(QGraphicsItem *item) = 0; virtual void removeItem(QGraphicsItem *item) = 0; + virtual void updateItem(QGraphicsItem *item); virtual void insertItems(const QList &items); virtual void removeItems(const QList &items); + virtual void updateItems(const QList &items); virtual QList items(const QRectF &rect) = 0; -- cgit v0.12 From 6df288191c5b6de8c6d1f00fd931401dc9f0c342 Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Tue, 17 Mar 2009 13:50:05 +0100 Subject: Fixes: Add API documentation for QGraphicsSceneIndex --- src/gui/graphicsview/qgraphicssceneindex.cpp | 80 ++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index cb84f6b..99d1b3b 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -46,38 +46,118 @@ QT_BEGIN_NAMESPACE +/*! + Constructs an abstract scene index. +*/ QGraphicsSceneIndex::QGraphicsSceneIndex() { } +/*! + Destroys the scene index. +*/ QGraphicsSceneIndex::~QGraphicsSceneIndex() { } +/*! + \fn virtual void setRect(const QRectF &rect) = 0 + + This pure virtual function is called when the scene changes its bounding + rectangle. + + \sa rect(), QGraphicsScene::setSceneRect +*/ + +/*! + \fn virtual QRectF rect() const = 0 + + This pure virtual function returns the bounding rectangle of this + scene index. It could be as large as or larger than the scene + bounding rectangle, depending on the implementation of the + scene index. + + \sa setRect(), QGraphicsScene::sceneRect +*/ + +/*! + \fn virtual void clear() = 0 + + This pure virtual function removes all items in the scene index. +*/ + +/*! + \fn virtual void insertItem(QGraphicsItem *item) = 0 + + This pure virtual function inserts an item to the scene index. + + \sa removeItem(), updateItem(), insertItems() +*/ + +/*! + \fn virtual void removeItem(QGraphicsItem *item) = 0 + + This pure virtual function removes an item to the scene index. + + \sa insertItem(), updateItem(), removeItems() +*/ + +/*! + Returns the scene of this scene index. +*/ QGraphicsScene* QGraphicsSceneIndex::scene() { return mscene; } +/*! + Updates an item when its geometry has changed. + + The default implemention will remove the item from the index + and then insert it again. + + \sa insertItem(), removeItem(), updateItems() +*/ void QGraphicsSceneIndex::updateItem(QGraphicsItem *item) { removeItem(item); insertItem(item); } +/*! + Inserts a list of items to the index. + + The default implemention will insert the items one by one. + + \sa insertItem(), removeItems(), updateItems() +*/ void QGraphicsSceneIndex::insertItems(const QList &items) { foreach (QGraphicsItem *item, items) insertItem(item); } +/*! + Removes a list of items from the index. + + The default implemention will remove the items one by one. + + \sa removeItem(), removeItems(), updateItems() +*/ void QGraphicsSceneIndex::removeItems(const QList &items) { foreach (QGraphicsItem *item, items) removeItem(item); } +/*! + Update a list of items which have changed the geometry. + + The default implemention will update the items one by one. + + \sa updateItem(), insertItems(), removeItems() +*/ void QGraphicsSceneIndex::updateItems(const QList &items) { foreach (QGraphicsItem *item, items) -- cgit v0.12 From 8e13ebc41ccbf4d1ec6ba552f8865007db5af875 Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Tue, 17 Mar 2009 14:56:04 +0100 Subject: Fixes: Add autotest for overlapped rectangles --- .../tst_qgraphicssceneindex.cpp | 29 ++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp index d199351..f03404e 100644 --- a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp +++ b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp @@ -63,6 +63,8 @@ private slots: void customIndex(); void scatteredItems_data(); void scatteredItems(); + void overlappedItems_data(); + void overlappedItems(); private: void common_data(); @@ -144,5 +146,32 @@ void tst_QGraphicsSceneIndex::scatteredItems() QCOMPARE(scene.items(QRectF(-100, -1000, 0, 0)).count(), 0); } +void tst_QGraphicsSceneIndex::overlappedItems_data() +{ + common_data(); +} + +void tst_QGraphicsSceneIndex::overlappedItems() +{ + QFETCH(QString, indexMethod); + QGraphicsSceneIndex *index = createIndex(indexMethod); + + QGraphicsScene scene; + scene.setSceneIndex(index); + + for (int i = 0; i < 10; ++i) + for (int j = 0; j < 10; ++j) + scene.addRect(i*50, j*50, 200, 200); + + QCOMPARE(scene.items(QRectF(0, 0, 1000, 1000)).count(), 100); + QCOMPARE(scene.items(QRectF(-100, -1000, 0, 0)).count(), 0); + QCOMPARE(scene.items(QRectF(0, 0, 200, 200)).count(), 16); + QCOMPARE(scene.items(QRectF(0, 0, 100, 100)).count(), 4); + QCOMPARE(scene.items(QRectF(0, 0, 1, 100)).count(), 2); + QCOMPARE(scene.items(QRectF(0, 0, 1, 1000)).count(), 10); +} + + + QTEST_MAIN(tst_QGraphicsSceneIndex) #include "tst_qgraphicssceneindex.moc" -- cgit v0.12 From 72f34ea254d2ad93e11f740bf2ed2523f1975ee9 Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Tue, 17 Mar 2009 15:04:52 +0100 Subject: Fixes: Add autotest for moving rectangle between items. --- .../tst_qgraphicssceneindex.cpp | 29 ++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp index f03404e..9a01cb8 100644 --- a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp +++ b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp @@ -65,6 +65,8 @@ private slots: void scatteredItems(); void overlappedItems_data(); void overlappedItems(); + void movingItems_data(); + void movingItems(); private: void common_data(); @@ -171,6 +173,33 @@ void tst_QGraphicsSceneIndex::overlappedItems() QCOMPARE(scene.items(QRectF(0, 0, 1, 1000)).count(), 10); } +void tst_QGraphicsSceneIndex::movingItems_data() +{ + common_data(); +} + +void tst_QGraphicsSceneIndex::movingItems() +{ + QFETCH(QString, indexMethod); + QGraphicsSceneIndex *index = createIndex(indexMethod); + + QGraphicsScene scene; + scene.setSceneIndex(index); + + for (int i = 0; i < 10; ++i) + scene.addRect(i*50, i*50, 40, 35); + + QGraphicsRectItem *box = scene.addRect(0, 0, 10, 10); + QCOMPARE(scene.items(QRectF(0, 0, 5, 5)).count(), 2); + + box->setPos(10, 10); + QCOMPARE(scene.items(QRectF(0, 0, 1, 1)).count(), 1); + + box->setPos(-5, -5); + QCOMPARE(scene.items(QRectF(0, 0, 1, 1)).count(), 2); + + QCOMPARE(scene.items(QRectF(0, 0, 1000, 1000)).count(), 11); +} QTEST_MAIN(tst_QGraphicsSceneIndex) -- cgit v0.12 From 22a3772006c34e51f446eb3ab1cfaf5e40cab583 Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Tue, 17 Mar 2009 15:07:53 +0100 Subject: Fixes: Remove from the custom index too (this will change anyway) --- src/gui/graphicsview/qgraphicsscene.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 8660853..77711ad 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -822,8 +822,13 @@ void QGraphicsScenePrivate::purgeRemovedItems() return; // Remove stale items from the BSP tree. - if (indexMethod != QGraphicsScene::NoIndex) - bspTree.removeItems(removedItems); + if (indexMethod != QGraphicsScene::NoIndex) { + if (indexMethod == QGraphicsScene::BspTreeIndex) { + bspTree.removeItems(removedItems); + } else { + customIndex->removeItems(removedItems); + } + } // Purge this list. removedItems.clear(); -- cgit v0.12 From 133bded765f224bce31d8abff87cc74a63569715 Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Tue, 17 Mar 2009 17:26:26 +0100 Subject: Fixes: The bsp and customs index share the same pointer --- src/gui/graphicsview/qgraphicsscene.cpp | 66 ++++++++++++++++++--------------- src/gui/graphicsview/qgraphicsscene_p.h | 6 ++- 2 files changed, 41 insertions(+), 31 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 77711ad..4070f11 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -331,7 +331,7 @@ QGraphicsScenePrivate::QGraphicsScenePrivate() indexMethod(QGraphicsScene::BspTreeIndex), bspTreeDepth(0), lastItemCount(0), - customIndex(0), + index(new QGraphicsSceneBspTree()), hasSceneRect(false), updateAll(false), calledEmitUpdated(false), @@ -361,7 +361,11 @@ QGraphicsScenePrivate::QGraphicsScenePrivate() style(0) { } - +QGraphicsScenePrivate::~QGraphicsScenePrivate() +{ + if (index) + delete index; +} /*! \internal */ @@ -388,13 +392,8 @@ QList QGraphicsScenePrivate::estimateItemsInRect(const QRectF & QGraphicsScenePrivate *that = const_cast(this); QList items; - if (indexMethod == QGraphicsScene::BspTreeIndex) { - // Get items from BSP tree - items = that->bspTree.items(rect); - } else { - //ask to the custom indexing - items = that->customIndex->items(rect); - } + // Get items from index + items = that->index->items(rect); // Fill in with any unindexed items for (int i = 0; i < unindexedItems.size(); ++i) { @@ -443,7 +442,7 @@ void QGraphicsScenePrivate::addToIndex(QGraphicsItem *item) { if (indexMethod == QGraphicsScene::BspTreeIndex) { if (item->d_func()->index != -1) { - bspTree.insertItem(item); + index->insertItem(item); foreach (QGraphicsItem *child, item->children()) child->addToIndex(); } else { @@ -454,7 +453,7 @@ void QGraphicsScenePrivate::addToIndex(QGraphicsItem *item) } } else if (indexMethod == QGraphicsScene::CustomIndex) { if (item->d_func()->index != -1) { - customIndex->insertItem(item); + index->insertItem(item); foreach (QGraphicsItem *child, item->children()) child->addToIndex(); } @@ -469,10 +468,7 @@ void QGraphicsScenePrivate::removeFromIndex(QGraphicsItem *item) if (indexMethod != QGraphicsScene::NoIndex) { int index = item->d_func()->index; if (index != -1) { - if (indexMethod == QGraphicsScene::CustomIndex) - customIndex->removeItem(item); - else - bspTree.removeItem(item); + this->index->removeItem(item); freeItemIndexes << index; indexedItems[index] = 0; item->d_func()->index = -1; @@ -551,7 +547,9 @@ void QGraphicsScenePrivate::_q_updateIndex() int oldDepth = intmaxlog(lastItemCount); depth = intmaxlog(indexedItems.size()); static const int slack = 100; - if (bspTree.leafCount() == 0 || (oldDepth != depth && qAbs(lastItemCount - indexedItems.size()) > slack)) { + //### do something better + QGraphicsSceneBspTree *bsp = static_cast(index); + if (bsp->leafCount() == 0 || (oldDepth != depth && qAbs(lastItemCount - indexedItems.size()) > slack)) { // ### Crude algorithm. regenerateIndex = true; } @@ -560,7 +558,9 @@ void QGraphicsScenePrivate::_q_updateIndex() // Regenerate the tree. if (regenerateIndex) { regenerateIndex = false; - bspTree.initialize(q->sceneRect(), depth); + //### do something better + QGraphicsSceneBspTree *bsp = static_cast(index); + bsp->initialize(q->sceneRect(), depth); unindexedItems = indexedItems; lastItemCount = indexedItems.size(); q->update(); @@ -578,10 +578,9 @@ void QGraphicsScenePrivate::_q_updateIndex() QRectF rect = item->sceneBoundingRect(); if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) continue; - if (indexMethod == QGraphicsScene::BspTreeIndex) - bspTree.insertItem(item); - if (indexMethod == QGraphicsScene::CustomIndex) - customIndex->insertItem(item); + + if (indexMethod != QGraphicsScene::NoIndex) + index->insertItem(item); // If the item ignores view transformations, update our // largest-item-counter to ensure that the view can accurately @@ -823,11 +822,7 @@ void QGraphicsScenePrivate::purgeRemovedItems() // Remove stale items from the BSP tree. if (indexMethod != QGraphicsScene::NoIndex) { - if (indexMethod == QGraphicsScene::BspTreeIndex) { - bspTree.removeItems(removedItems); - } else { - customIndex->removeItems(removedItems); - } + index->removeItems(removedItems); } // Purge this list. @@ -2386,8 +2381,18 @@ void QGraphicsScene::setItemIndexMethod(ItemIndexMethod method) qWarning("QGraphicsScene: Invalid index type %d", CustomIndex); return; } + if (d->indexMethod == method) { + return; + } d->resetIndex(); + if (d->indexMethod != NoIndex) { + delete d->index; + } d->indexMethod = method; + if (method == BspTreeIndex) { + d->index = new QGraphicsSceneBspTree(); + } + } void QGraphicsScene::setSceneIndex(QGraphicsSceneIndex *index) @@ -2396,8 +2401,11 @@ void QGraphicsScene::setSceneIndex(QGraphicsSceneIndex *index) if (!index) { qWarning("QGraphicsScene::setSceneIndex: Attempt to insert a null indexer"); } else { + if (d->indexMethod == BspTreeIndex) { + delete d->index; + } d->indexMethod = CustomIndex; - d->customIndex = index; + d->index = index; index->mscene = this; } } @@ -2405,7 +2413,7 @@ void QGraphicsScene::setSceneIndex(QGraphicsSceneIndex *index) QGraphicsSceneIndex* QGraphicsScene::sceneIndex() const { Q_D(const QGraphicsScene); - return d->customIndex; + return d->index; } /*! @@ -2814,7 +2822,7 @@ void QGraphicsScene::clear() d->indexedItems.clear(); d->freeItemIndexes.clear(); d->lastItemCount = 0; - d->bspTree.clear(); + d->index->clear(); d->largestUntransformableItem = QRectF(); d->allItemsIgnoreHoverEvents = true; d->allItemsUseDefaultCursor = true; diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index aacbc40..b06db38 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -58,6 +58,7 @@ #if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW #include "qgraphicsscene_bsp_p.h" +#include "qgraphicsscene_linear_p.h" #include "qgraphicssceneindex.h" #include "qgraphicsitem_p.h" @@ -80,6 +81,7 @@ class QGraphicsScenePrivate : public QObjectPrivate Q_DECLARE_PUBLIC(QGraphicsScene) public: QGraphicsScenePrivate(); + ~QGraphicsScenePrivate(); void init(); quint32 changedSignalMask; @@ -92,11 +94,11 @@ public: void removeFromIndex(QGraphicsItem *item); void resetIndex(); - QGraphicsSceneBspTree bspTree; void _q_updateIndex(); int lastItemCount; - QGraphicsSceneIndex *customIndex; + QGraphicsSceneIndex *index; + QGraphicsSceneLinearIndex *linearIndex; QRectF sceneRect; bool hasSceneRect; -- cgit v0.12 From 5cf43cf62221e3241e33ea25efc7014c07e4d7ad Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Tue, 7 Apr 2009 20:20:53 +0200 Subject: Fixes: Add new virtual QGraphicsSceneIndex::items(QPointF) --- src/gui/graphicsview/qgraphicsscene_bsp_p.h | 3 +-- src/gui/graphicsview/qgraphicsscene_linear_p.h | 8 ++++++++ src/gui/graphicsview/qgraphicssceneindex.h | 1 + 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene_bsp_p.h b/src/gui/graphicsview/qgraphicsscene_bsp_p.h index a8c54f0..ed207ea 100644 --- a/src/gui/graphicsview/qgraphicsscene_bsp_p.h +++ b/src/gui/graphicsview/qgraphicsscene_bsp_p.h @@ -95,14 +95,13 @@ public: void removeItem(QGraphicsItem *item); void removeItems(const QList &items); + QList items(const QPointF &point); QList items(const QRectF &rect); int leafCount() const; private: - QList items(const QPointF &pos); - inline int firstChildIndex(int index) const { return index * 2 + 1; } diff --git a/src/gui/graphicsview/qgraphicsscene_linear_p.h b/src/gui/graphicsview/qgraphicsscene_linear_p.h index 1ef1902..1981b17 100644 --- a/src/gui/graphicsview/qgraphicsscene_linear_p.h +++ b/src/gui/graphicsview/qgraphicsscene_linear_p.h @@ -94,6 +94,14 @@ public: m_items.removeAll(item); } + virtual QList items(const QPointF &point) { + QList result; + foreach (QGraphicsItem *item, m_items) + if (item->sceneBoundingRect().contains(point)) + result << item; + return result; + } + virtual QList items(const QRectF &rect) { QList result; foreach (QGraphicsItem *item, m_items) diff --git a/src/gui/graphicsview/qgraphicssceneindex.h b/src/gui/graphicsview/qgraphicssceneindex.h index 6246753..f78672f 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.h +++ b/src/gui/graphicsview/qgraphicssceneindex.h @@ -76,6 +76,7 @@ public: virtual void removeItems(const QList &items); virtual void updateItems(const QList &items); + virtual QList items(const QPointF &point) = 0; virtual QList items(const QRectF &rect) = 0; QGraphicsScene* scene(); -- cgit v0.12 From 875d5f41b1a796d91a4a8edac6c23a7965395470 Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Wed, 18 Mar 2009 15:36:41 +0100 Subject: Fixes: Autotest the scene index using the new items(QPointF) function. --- tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp index 9a01cb8..955f2d3 100644 --- a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp +++ b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp @@ -143,6 +143,10 @@ void tst_QGraphicsSceneIndex::scatteredItems() for (int i = 0; i < 10; ++i) scene.addRect(i*50, i*50, 40, 35); + QCOMPARE(scene.items(QPointF(5, 5)).count(), 1); + QCOMPARE(scene.items(QPointF(55, 55)).count(), 1); + QCOMPARE(scene.items(QPointF(-100, -100)).count(), 0); + QCOMPARE(scene.items(QRectF(0, 0, 10, 10)).count(), 1); QCOMPARE(scene.items(QRectF(0, 0, 1000, 1000)).count(), 10); QCOMPARE(scene.items(QRectF(-100, -1000, 0, 0)).count(), 0); @@ -165,6 +169,11 @@ void tst_QGraphicsSceneIndex::overlappedItems() for (int j = 0; j < 10; ++j) scene.addRect(i*50, j*50, 200, 200); + QCOMPARE(scene.items(QPointF(5, 5)).count(), 1); + QCOMPARE(scene.items(QPointF(55, 55)).count(), 4); + QCOMPARE(scene.items(QPointF(105, 105)).count(), 9); + QCOMPARE(scene.items(QPointF(-100, -100)).count(), 0); + QCOMPARE(scene.items(QRectF(0, 0, 1000, 1000)).count(), 100); QCOMPARE(scene.items(QRectF(-100, -1000, 0, 0)).count(), 0); QCOMPARE(scene.items(QRectF(0, 0, 200, 200)).count(), 16); @@ -190,12 +199,17 @@ void tst_QGraphicsSceneIndex::movingItems() scene.addRect(i*50, i*50, 40, 35); QGraphicsRectItem *box = scene.addRect(0, 0, 10, 10); + QCOMPARE(scene.items(QPointF(5, 5)).count(), 2); + QCOMPARE(scene.items(QPointF(-1, -1)).count(), 0); QCOMPARE(scene.items(QRectF(0, 0, 5, 5)).count(), 2); box->setPos(10, 10); + QCOMPARE(scene.items(QPointF(9, 9)).count(), 1); + QCOMPARE(scene.items(QPointF(15, 15)).count(), 2); QCOMPARE(scene.items(QRectF(0, 0, 1, 1)).count(), 1); box->setPos(-5, -5); + QCOMPARE(scene.items(QPointF(-1, -1)).count(), 1); QCOMPARE(scene.items(QRectF(0, 0, 1, 1)).count(), 2); QCOMPARE(scene.items(QRectF(0, 0, 1000, 1000)).count(), 11); -- cgit v0.12 From 76b8d22cee1d0a12de30f2c9d49ead5625b5122f Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Wed, 18 Mar 2009 16:33:03 +0100 Subject: Fixes: QGraphicsSceneIndex now inherits from QObject --- src/gui/graphicsview/qgraphicsscene_bsp.cpp | 4 ++-- src/gui/graphicsview/qgraphicsscene_bsp_p.h | 4 +++- src/gui/graphicsview/qgraphicsscene_linear_p.h | 4 +++- src/gui/graphicsview/qgraphicssceneindex.cpp | 4 ++-- src/gui/graphicsview/qgraphicssceneindex.h | 7 +++++-- 5 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene_bsp.cpp b/src/gui/graphicsview/qgraphicsscene_bsp.cpp index b73cba2..29c54bb 100644 --- a/src/gui/graphicsview/qgraphicsscene_bsp.cpp +++ b/src/gui/graphicsview/qgraphicsscene_bsp.cpp @@ -83,8 +83,8 @@ public: } }; -QGraphicsSceneBspTree::QGraphicsSceneBspTree() - : leafCnt(0) +QGraphicsSceneBspTree::QGraphicsSceneBspTree(QObject *parent) + : QGraphicsSceneIndex(parent), leafCnt(0) { insertVisitor = new QGraphicsSceneInsertItemBspTreeVisitor; removeVisitor = new QGraphicsSceneRemoveItemBspTreeVisitor; diff --git a/src/gui/graphicsview/qgraphicsscene_bsp_p.h b/src/gui/graphicsview/qgraphicsscene_bsp_p.h index ed207ea..8b7d753 100644 --- a/src/gui/graphicsview/qgraphicsscene_bsp_p.h +++ b/src/gui/graphicsview/qgraphicsscene_bsp_p.h @@ -72,6 +72,8 @@ class QGraphicsSceneFindItemBspTreeVisitor; class Q_AUTOTEST_EXPORT QGraphicsSceneBspTree : public QGraphicsSceneIndex { + Q_OBJECT + public: struct Node { @@ -83,7 +85,7 @@ public: Type type; }; - QGraphicsSceneBspTree(); + QGraphicsSceneBspTree(QObject *parent = 0); ~QGraphicsSceneBspTree(); void initialize(const QRectF &rect, int depth); diff --git a/src/gui/graphicsview/qgraphicsscene_linear_p.h b/src/gui/graphicsview/qgraphicsscene_linear_p.h index 1981b17..4871b2c 100644 --- a/src/gui/graphicsview/qgraphicsscene_linear_p.h +++ b/src/gui/graphicsview/qgraphicsscene_linear_p.h @@ -66,12 +66,14 @@ QT_BEGIN_NAMESPACE class Q_AUTOTEST_EXPORT QGraphicsSceneLinearIndex : public QGraphicsSceneIndex { + Q_OBJECT + private: QRectF m_sceneRect; QList m_items; public: - QGraphicsSceneLinearIndex(): QGraphicsSceneIndex() { + QGraphicsSceneLinearIndex(QObject *parent = 0): QGraphicsSceneIndex(parent) { } virtual void setRect(const QRectF &rect) { diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index 99d1b3b..904e0af 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -49,7 +49,7 @@ QT_BEGIN_NAMESPACE /*! Constructs an abstract scene index. */ -QGraphicsSceneIndex::QGraphicsSceneIndex() +QGraphicsSceneIndex::QGraphicsSceneIndex(QObject *parent): QObject(parent) { } @@ -166,6 +166,6 @@ void QGraphicsSceneIndex::updateItems(const QList &items) QT_END_NAMESPACE -//#include "moc_qgraphicssceneindex.cpp" +#include "moc_qgraphicssceneindex.cpp" #endif // QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicssceneindex.h b/src/gui/graphicsview/qgraphicssceneindex.h index f78672f..d3b6c9f 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.h +++ b/src/gui/graphicsview/qgraphicssceneindex.h @@ -43,6 +43,7 @@ #define QGRAPHICSSCENEINDEX_H #include +#include QT_BEGIN_HEADER @@ -58,10 +59,12 @@ class QRectF; class QPointF; template class QList; -class Q_GUI_EXPORT QGraphicsSceneIndex +class Q_GUI_EXPORT QGraphicsSceneIndex: public QObject { + Q_OBJECT + public: - QGraphicsSceneIndex(); + QGraphicsSceneIndex(QObject *parent = 0); virtual ~QGraphicsSceneIndex(); virtual void setRect(const QRectF &rect) = 0; -- cgit v0.12 From dfd72ab3c8e519f2c08b9a85e1309f8e06a5dd45 Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Wed, 18 Mar 2009 19:49:55 +0100 Subject: Fixes: 'delete' always works even with null pointer. --- src/gui/graphicsview/qgraphicsscene.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 4070f11..dd67067 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -363,8 +363,7 @@ QGraphicsScenePrivate::QGraphicsScenePrivate() } QGraphicsScenePrivate::~QGraphicsScenePrivate() { - if (index) - delete index; + delete index; } /*! \internal -- cgit v0.12 From 31bba59443638a2f97f330a9b64ded261b060701 Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Wed, 18 Mar 2009 20:16:55 +0100 Subject: Fixes: Own our internal scene index so we do not need to explicitly delete it. --- src/gui/graphicsview/qgraphicsscene.cpp | 7 +++---- src/gui/graphicsview/qgraphicsscene_p.h | 1 - 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index dd67067..d4fcbd0 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -361,10 +361,7 @@ QGraphicsScenePrivate::QGraphicsScenePrivate() style(0) { } -QGraphicsScenePrivate::~QGraphicsScenePrivate() -{ - delete index; -} + /*! \internal */ @@ -372,6 +369,8 @@ void QGraphicsScenePrivate::init() { Q_Q(QGraphicsScene); + index->setParent(q); + // Keep this index so we can check for connected slots later on. changedSignalMask = (1 << q->metaObject()->indexOfSignal("changed(QList)")); qApp->d_func()->scene_list.append(q); diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index b06db38..7e311ee 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -81,7 +81,6 @@ class QGraphicsScenePrivate : public QObjectPrivate Q_DECLARE_PUBLIC(QGraphicsScene) public: QGraphicsScenePrivate(); - ~QGraphicsScenePrivate(); void init(); quint32 changedSignalMask; -- cgit v0.12 From 980e01d69a29e2710a954e2bcd47d78039c76dbd Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Wed, 18 Mar 2009 20:21:36 +0100 Subject: Fixes: Recreate the BSP tree properly. --- src/gui/graphicsview/qgraphicsscene.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index d4fcbd0..4b40d3b 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -2383,14 +2383,12 @@ void QGraphicsScene::setItemIndexMethod(ItemIndexMethod method) return; } d->resetIndex(); - if (d->indexMethod != NoIndex) { + if (method == BspTreeIndex) { delete d->index; + d->index = new QGraphicsSceneBspTree(this); + // ### FIXME: transfer the items } d->indexMethod = method; - if (method == BspTreeIndex) { - d->index = new QGraphicsSceneBspTree(); - } - } void QGraphicsScene::setSceneIndex(QGraphicsSceneIndex *index) -- cgit v0.12 From f4c03e0eec3b39145471f25d0a1cdcdba604790c Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Wed, 18 Mar 2009 20:41:27 +0100 Subject: Fixes: Recreate the index properly when switching the index method. --- src/gui/graphicsview/qgraphicsscene.cpp | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 4b40d3b..f8f8e98 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -2372,6 +2372,17 @@ QGraphicsScene::ItemIndexMethod QGraphicsScene::itemIndexMethod() const Q_D(const QGraphicsScene); return d->indexMethod; } + +// Possibilities +// NoIndex -> CustomIndex : warning +// BspTreeIndex -> CustomIndex : warning +// CustomIndex -> CustomIndex : warning +// NoIndex -> BspTreeIndex : create an empty BSP if necessary +// BspTreeIndex -> BspTreeIndex : nothing +// CustomIndex -> BspTreeIndex : create BSP and transfer items +// NoIndex -> NoIndex : nothing +// BspTreeIndex -> NoIndex : nothing +// CustomIndex -> NoIndex : create BSP tree but do not populate void QGraphicsScene::setItemIndexMethod(ItemIndexMethod method) { Q_D(QGraphicsScene); @@ -2383,11 +2394,25 @@ void QGraphicsScene::setItemIndexMethod(ItemIndexMethod method) return; } d->resetIndex(); - if (method == BspTreeIndex) { - delete d->index; + + if (d->indexMethod == NoIndex && method == BspTreeIndex) { + QGraphicsSceneBspTree *tree = qobject_cast(d->index); + if (!tree) { + delete d->index; + d->index = new QGraphicsSceneBspTree(this); + } + } + + if (d->indexMethod == CustomIndex && method == BspTreeIndex) { + QGraphicsSceneIndex *oldIndex = d->index; d->index = new QGraphicsSceneBspTree(this); - // ### FIXME: transfer the items + d->index->insertItems(oldIndex->items(oldIndex->rect())); } + + if (d->indexMethod == CustomIndex && method == NoIndex) { + d->index = new QGraphicsSceneBspTree(this); + } + d->indexMethod = method; } -- cgit v0.12 From ce77e1d327653c2c0724d6d4a45564c25d98eda8 Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Thu, 19 Mar 2009 11:26:24 +0100 Subject: Fixes: Move the bsp depth variable to the BSP tree class. --- src/gui/graphicsview/qgraphicsscene.cpp | 16 ++++++++++++---- src/gui/graphicsview/qgraphicsscene_bsp.cpp | 2 +- src/gui/graphicsview/qgraphicsscene_bsp_p.h | 2 ++ 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index f8f8e98..6aab9df 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -329,7 +329,6 @@ static void _q_hoverFromMouseEvent(QGraphicsSceneHoverEvent *hover, const QGraph QGraphicsScenePrivate::QGraphicsScenePrivate() : changedSignalMask(0), indexMethod(QGraphicsScene::BspTreeIndex), - bspTreeDepth(0), lastItemCount(0), index(new QGraphicsSceneBspTree()), hasSceneRect(false), @@ -540,7 +539,9 @@ void QGraphicsScenePrivate::_q_updateIndex() // Determine whether we should regenerate the BSP tree. if (indexMethod == QGraphicsScene::BspTreeIndex) { - int depth = bspTreeDepth; + QGraphicsSceneBspTree *bspTree = qobject_cast(index); + Q_ASSERT(bspTree); + int depth = bspTree->depth; if (depth == 0) { int oldDepth = intmaxlog(lastItemCount); depth = intmaxlog(indexedItems.size()); @@ -2472,7 +2473,8 @@ QGraphicsSceneIndex* QGraphicsScene::sceneIndex() const int QGraphicsScene::bspTreeDepth() const { Q_D(const QGraphicsScene); - return d->bspTreeDepth; + QGraphicsSceneBspTree *bspTree = qobject_cast(d->index); + return bspTree ? bspTree->depth : 0; } void QGraphicsScene::setBspTreeDepth(int depth) { @@ -2485,7 +2487,13 @@ void QGraphicsScene::setBspTreeDepth(int depth) return; } - d->bspTreeDepth = depth; + QGraphicsSceneBspTree *bspTree = qobject_cast(d->index); + if (!bspTree) { + qWarning("QGraphicsScene::setBspTreeDepth: can not apply if indexing method is not BSP"); + return; + } + + bspTree->depth = depth; d->resetIndex(); } diff --git a/src/gui/graphicsview/qgraphicsscene_bsp.cpp b/src/gui/graphicsview/qgraphicsscene_bsp.cpp index 29c54bb..a81b14d 100644 --- a/src/gui/graphicsview/qgraphicsscene_bsp.cpp +++ b/src/gui/graphicsview/qgraphicsscene_bsp.cpp @@ -84,7 +84,7 @@ public: }; QGraphicsSceneBspTree::QGraphicsSceneBspTree(QObject *parent) - : QGraphicsSceneIndex(parent), leafCnt(0) + : QGraphicsSceneIndex(parent), depth(0), leafCnt(0) { insertVisitor = new QGraphicsSceneInsertItemBspTreeVisitor; removeVisitor = new QGraphicsSceneRemoveItemBspTreeVisitor; diff --git a/src/gui/graphicsview/qgraphicsscene_bsp_p.h b/src/gui/graphicsview/qgraphicsscene_bsp_p.h index 8b7d753..69d9eee 100644 --- a/src/gui/graphicsview/qgraphicsscene_bsp_p.h +++ b/src/gui/graphicsview/qgraphicsscene_bsp_p.h @@ -102,6 +102,8 @@ public: int leafCount() const; + int depth; + private: inline int firstChildIndex(int index) const -- cgit v0.12 From a779817905ae66de9333fbe3896b0ff1c3990581 Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Thu, 19 Mar 2009 14:23:41 +0100 Subject: Fixes: First step to remove the indexing logic inside the scene. This commit basically remove the list of unindexingItems and use the linear index instead. Details: We now must be able to get rid of the timer which is the BSP role. --- src/gui/graphicsview/qgraphicsscene.cpp | 117 ++++++++++++------------- src/gui/graphicsview/qgraphicsscene_linear_p.h | 4 + src/gui/graphicsview/qgraphicsscene_p.h | 1 - 3 files changed, 60 insertions(+), 62 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 6aab9df..b559835 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -331,6 +331,7 @@ QGraphicsScenePrivate::QGraphicsScenePrivate() indexMethod(QGraphicsScene::BspTreeIndex), lastItemCount(0), index(new QGraphicsSceneBspTree()), + linearIndex(new QGraphicsSceneLinearIndex()), hasSceneRect(false), updateAll(false), calledEmitUpdated(false), @@ -369,6 +370,7 @@ void QGraphicsScenePrivate::init() Q_Q(QGraphicsScene); index->setParent(q); + linearIndex->setParent(q); // Keep this index so we can check for connected slots later on. changedSignalMask = (1 << q->metaObject()->indexOfSignal("changed(QList)")); @@ -392,16 +394,13 @@ QList QGraphicsScenePrivate::estimateItemsInRect(const QRectF & // Get items from index items = that->index->items(rect); + //### Why there are items indexed and not at some point? + // Fill in with any unindexed items - for (int i = 0; i < unindexedItems.size(); ++i) { - if (QGraphicsItem *item = unindexedItems.at(i)) { - if (!item->d_ptr->itemDiscovered && item->d_ptr->visible && !(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) { - QRectF boundingRect = item->sceneBoundingRect(); - if (QRectF_intersects(boundingRect, rect)) { - item->d_ptr->itemDiscovered = 1; - items << item; - } - } + foreach (QGraphicsItem *item, linearIndex->items(rect)) { + if (!item->d_ptr->itemDiscovered && item->d_ptr->visible && !(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) { + item->d_ptr->itemDiscovered = 1; + items << item; } } @@ -412,14 +411,15 @@ QList QGraphicsScenePrivate::estimateItemsInRect(const QRectF & } QList itemsInRect; - for (int i = 0; i < unindexedItems.size(); ++i) { - if (QGraphicsItem *item = unindexedItems.at(i)) { - if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) - continue; - if (item->d_ptr->visible && item->effectiveOpacity() > qreal(0.0)) - itemsInRect << item; - } + foreach (QGraphicsItem *item, linearIndex->items(rect)) { + if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) + continue; + if (item->d_ptr->visible && item->effectiveOpacity() > qreal(0.0)) + itemsInRect << item; } + + //### Why there are items indexed and not at some point? + for (int i = 0; i < indexedItems.size(); ++i) { if (QGraphicsItem *item = indexedItems.at(i)) { if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) @@ -469,7 +469,7 @@ void QGraphicsScenePrivate::removeFromIndex(QGraphicsItem *item) freeItemIndexes << index; indexedItems[index] = 0; item->d_func()->index = -1; - unindexedItems << item; + linearIndex->insertItem(item); foreach (QGraphicsItem *child, item->children()) child->removeFromIndex(); @@ -488,7 +488,7 @@ void QGraphicsScenePrivate::resetIndex() for (int i = 0; i < indexedItems.size(); ++i) { if (QGraphicsItem *item = indexedItems.at(i)) { item->d_ptr->index = -1; - unindexedItems << item; + linearIndex->insertItem(item); } } indexedItems.clear(); @@ -519,17 +519,15 @@ void QGraphicsScenePrivate::_q_updateIndex() // Add unindexedItems to indexedItems QRectF unindexedItemsBoundingRect; - for (int i = 0; i < unindexedItems.size(); ++i) { - if (QGraphicsItem *item = unindexedItems.at(i)) { - unindexedItemsBoundingRect |= item->sceneBoundingRect(); - if (!freeItemIndexes.isEmpty()) { - int freeIndex = freeItemIndexes.takeFirst(); - item->d_func()->index = freeIndex; - indexedItems[freeIndex] = item; - } else { - item->d_func()->index = indexedItems.size(); - indexedItems << item; - } + foreach (QGraphicsItem *item, linearIndex->indexedItems()) { + unindexedItemsBoundingRect |= item->sceneBoundingRect(); + if (!freeItemIndexes.isEmpty()) { + int freeIndex = freeItemIndexes.takeFirst(); + item->d_func()->index = freeIndex; + indexedItems[freeIndex] = item; + } else { + item->d_func()->index = indexedItems.size(); + indexedItems << item; } } @@ -560,7 +558,8 @@ void QGraphicsScenePrivate::_q_updateIndex() //### do something better QGraphicsSceneBspTree *bsp = static_cast(index); bsp->initialize(q->sceneRect(), depth); - unindexedItems = indexedItems; + foreach (QGraphicsItem *item, indexedItems) + linearIndex->insertItem(item); lastItemCount = indexedItems.size(); q->update(); @@ -572,30 +571,28 @@ void QGraphicsScenePrivate::_q_updateIndex() } // Insert all unindexed items into the tree. - for (int i = 0; i < unindexedItems.size(); ++i) { - if (QGraphicsItem *item = unindexedItems.at(i)) { - QRectF rect = item->sceneBoundingRect(); - if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) - continue; + foreach (QGraphicsItem *item, linearIndex->indexedItems()) { + QRectF rect = item->sceneBoundingRect(); + if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) + continue; - if (indexMethod != QGraphicsScene::NoIndex) - index->insertItem(item); - - // If the item ignores view transformations, update our - // largest-item-counter to ensure that the view can accurately - // discover untransformable items when drawing. - if (item->d_ptr->itemIsUntransformable()) { - QGraphicsItem *topmostUntransformable = item; - while (topmostUntransformable && (topmostUntransformable->d_ptr->ancestorFlags - & QGraphicsItemPrivate::AncestorIgnoresTransformations)) { - topmostUntransformable = topmostUntransformable->parentItem(); - } - // ### Verify that this is the correct largest untransformable rectangle. - largestUntransformableItem |= item->mapToItem(topmostUntransformable, item->boundingRect()).boundingRect(); + if (indexMethod != QGraphicsScene::NoIndex) + index->insertItem(item); + + // If the item ignores view transformations, update our + // largest-item-counter to ensure that the view can accurately + // discover untransformable items when drawing. + if (item->d_ptr->itemIsUntransformable()) { + QGraphicsItem *topmostUntransformable = item; + while (topmostUntransformable && (topmostUntransformable->d_ptr->ancestorFlags + & QGraphicsItemPrivate::AncestorIgnoresTransformations)) { + topmostUntransformable = topmostUntransformable->parentItem(); } + // ### Verify that this is the correct largest untransformable rectangle. + largestUntransformableItem |= item->mapToItem(topmostUntransformable, item->boundingRect()).boundingRect(); } } - unindexedItems.clear(); + linearIndex->clear(); // Notify scene rect changes. if (!hasSceneRect && growingItemsBoundingRect != oldGrowingItemsBoundingRect) @@ -756,7 +753,7 @@ void QGraphicsScenePrivate::_q_removeItemLater(QGraphicsItem *item) } else { // Recently added items are purged immediately. unindexedItems() never // contains stale items. - unindexedItems.removeAll(item); + linearIndex->removeItem(item); q->update(); } @@ -1982,8 +1979,7 @@ void QGraphicsScenePrivate::_q_updateSortCache() if (item && item->parentItem() == 0) topLevels << item; } - for (int i = 0; i < unindexedItems.size(); ++i) { - QGraphicsItem *item = unindexedItems.at(i); + foreach (QGraphicsItem *item, linearIndex->indexedItems()) { if (item->parentItem() == 0) topLevels << item; } @@ -2552,15 +2548,15 @@ QList QGraphicsScene::items() const // If freeItemIndexes is empty, we know there are no holes in indexedItems and // unindexedItems. if (d->freeItemIndexes.isEmpty()) { - if (d->unindexedItems.isEmpty()) + if (d->linearIndex->indexedItems().isEmpty()) return d->indexedItems; - return d->indexedItems + d->unindexedItems; + return d->indexedItems + d->linearIndex->indexedItems(); } // Rebuild the list of items to avoid holes. ### We could also just // compress the item lists at this point. QList itemList; - foreach (QGraphicsItem *item, d->indexedItems + d->unindexedItems) { + foreach (QGraphicsItem *item, d->indexedItems + d->linearIndex->indexedItems()) { if (item) itemList << item; } @@ -2841,12 +2837,11 @@ void QGraphicsScene::clear() } } QList unindexedParents; - for (int i = 0; i < d->unindexedItems.size(); ++i) { - QGraphicsItem *item = d->unindexedItems.at(i); + foreach (QGraphicsItem *item, d->linearIndex->indexedItems()) { if (!item->parentItem()) unindexedParents << item; } - d->unindexedItems.clear(); + d->linearIndex->clear(); qDeleteAll(unindexedParents); d->indexedItems.clear(); d->freeItemIndexes.clear(); @@ -2994,7 +2989,7 @@ void QGraphicsScene::addItem(QGraphicsItem *item) // Indexing requires sceneBoundingRect(), but because \a item might // not be completely constructed at this point, we need to store it in // a temporary list and schedule an indexing for later. - d->unindexedItems << item; + d->linearIndex->insertItem(item); item->d_func()->index = -1; d->startIndexTimer(); @@ -3382,7 +3377,7 @@ void QGraphicsScene::removeItem(QGraphicsItem *item) d->freeItemIndexes << index; d->indexedItems[index] = 0; } else { - d->unindexedItems.removeAll(item); + d->linearIndex->removeItem(item); } // Remove from scene transform cache diff --git a/src/gui/graphicsview/qgraphicsscene_linear_p.h b/src/gui/graphicsview/qgraphicsscene_linear_p.h index 4871b2c..41e03e4 100644 --- a/src/gui/graphicsview/qgraphicsscene_linear_p.h +++ b/src/gui/graphicsview/qgraphicsscene_linear_p.h @@ -111,6 +111,10 @@ public: result << item; return result; } + + QList indexedItems() { + return m_items; + } }; QT_END_NAMESPACE diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 7e311ee..65c1a69 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -112,7 +112,6 @@ public: QPainterPath selectionArea; int selectionChanging; QSet selectedItems; - QList unindexedItems; QList indexedItems; QList dirtyItems; QList pendingUpdateItems; -- cgit v0.12 From 226baa99f53eeeff2489148c9187c19f5bc86f0e Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Tue, 7 Apr 2009 20:42:53 +0200 Subject: Remove the indexing (BSP) logic from the scene We basically add a new index that implement the old BSP logic but in a separate class instead of living into the QGraphicsScene. It will be much more easier to add a new index method or for people to use their own Conflicts: src/gui/graphicsview/qgraphicsitem.cpp src/gui/graphicsview/qgraphicssceneindex.h --- src/gui/graphicsview/graphicsview.pri | 4 +- src/gui/graphicsview/qgraphicsitem.cpp | 10 +- src/gui/graphicsview/qgraphicsitem.h | 1 + src/gui/graphicsview/qgraphicsscene.cpp | 390 ++---------------- src/gui/graphicsview/qgraphicsscene.h | 2 +- src/gui/graphicsview/qgraphicsscene_bsp.cpp | 40 +- src/gui/graphicsview/qgraphicsscene_bsp_p.h | 27 +- src/gui/graphicsview/qgraphicsscene_linear_p.h | 124 ------ src/gui/graphicsview/qgraphicsscene_p.h | 20 +- .../graphicsview/qgraphicsscenebsptreeindex_p.cpp | 437 +++++++++++++++++++++ .../graphicsview/qgraphicsscenebsptreeindex_p.h | 118 ++++++ src/gui/graphicsview/qgraphicssceneindex.cpp | 14 +- src/gui/graphicsview/qgraphicssceneindex.h | 15 +- src/gui/graphicsview/qgraphicsscenelinearindex_p.h | 126 ++++++ .../tst_qgraphicssceneindex.cpp | 15 +- 15 files changed, 769 insertions(+), 574 deletions(-) delete mode 100644 src/gui/graphicsview/qgraphicsscene_linear_p.h create mode 100644 src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp create mode 100644 src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h create mode 100644 src/gui/graphicsview/qgraphicsscenelinearindex_p.h diff --git a/src/gui/graphicsview/graphicsview.pri b/src/gui/graphicsview/graphicsview.pri index bc4d9dd..9097497 100644 --- a/src/gui/graphicsview/graphicsview.pri +++ b/src/gui/graphicsview/graphicsview.pri @@ -6,8 +6,9 @@ HEADERS += \ graphicsview/qgraphicsitemanimation.h \ graphicsview/qgraphicsscene.h \ graphicsview/qgraphicsscene_p.h \ + graphicsview/qgraphicsscenebsptreeindex_p.h \ graphicsview/qgraphicsscene_bsp_p.h \ - graphicsview/qgraphicsscene_linear_p.h \ + graphicsview/qgraphicsscenelinearindex_p.h \ graphicsview/qgraphicssceneindex.h \ graphicsview/qgraphicssceneevent.h \ graphicsview/qgraphicsview_p.h \ @@ -18,6 +19,7 @@ SOURCES += \ graphicsview/qgraphicsitemanimation.cpp \ graphicsview/qgraphicsscene.cpp \ graphicsview/qgraphicsscene_bsp.cpp \ + graphicsview/qgraphicsscenebsptreeindex_p.cpp \ graphicsview/qgraphicssceneindex.cpp \ graphicsview/qgraphicssceneevent.cpp \ graphicsview/qgraphicsview.cpp diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index b8ff5b4..4574334 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -5789,7 +5789,7 @@ void QGraphicsItem::addToIndex() return; } if (d_ptr->scene) - d_ptr->scene->d_func()->addToIndex(this); + d_ptr->scene->d_func()->index->insertItem(this); d_ptr->updateHelper(); } @@ -5802,13 +5802,9 @@ void QGraphicsItem::addToIndex() */ void QGraphicsItem::removeFromIndex() { - if (d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) { - // ### remove from child index only if applicable - return; - } d_ptr->updateHelper(); if (d_ptr->scene) - d_ptr->scene->d_func()->removeFromIndex(this); + d_ptr->scene->d_func()->index->removeItem(this,false); } /*! @@ -5831,7 +5827,7 @@ void QGraphicsItem::prepareGeometryChange() d_ptr->updateHelper(QRectF(), false, /*maybeDirtyClipPath=*/!d_ptr->inSetPosHelper); QGraphicsScenePrivate *scenePrivate = d_ptr->scene->d_func(); - scenePrivate->removeFromIndex(this); + scenePrivate->index->updateItem(this); if (d_ptr->inSetPosHelper) return; diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index b98882d..1b41232 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -398,6 +398,7 @@ private: friend class QGraphicsWidget; friend class QGraphicsWidgetPrivate; friend class QGraphicsProxyWidgetPrivate; + friend class QGraphicsSceneBspTreeIndex; friend class ::tst_QGraphicsItem; friend bool qt_closestLeaf(const QGraphicsItem *, const QGraphicsItem *); friend bool qt_closestItemFirst(const QGraphicsItem *, const QGraphicsItem *); diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index b559835..8140f79 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -39,8 +39,6 @@ ** ****************************************************************************/ -static const int QGRAPHICSSCENE_INDEXTIMER_TIMEOUT = 2000; - /*! \class QGraphicsScene \brief The QGraphicsScene class provides a surface for managing a large @@ -329,18 +327,14 @@ static void _q_hoverFromMouseEvent(QGraphicsSceneHoverEvent *hover, const QGraph QGraphicsScenePrivate::QGraphicsScenePrivate() : changedSignalMask(0), indexMethod(QGraphicsScene::BspTreeIndex), + bspTreeDepth(0), lastItemCount(0), - index(new QGraphicsSceneBspTree()), - linearIndex(new QGraphicsSceneLinearIndex()), + index(0), hasSceneRect(false), updateAll(false), calledEmitUpdated(false), selectionChanging(0), dirtyItemResetPending(false), - regenerateIndex(true), - purgePending(false), - indexTimerId(0), - restartIndexTimer(false), stickyFocus(false), hasFocus(false), focusItem(0), @@ -369,8 +363,7 @@ void QGraphicsScenePrivate::init() { Q_Q(QGraphicsScene); - index->setParent(q); - linearIndex->setParent(q); + index = new QGraphicsSceneBspTreeIndex(q); // Keep this index so we can check for connected slots later on. changedSignalMask = (1 << q->metaObject()->indexOfSignal("changed(QList)")); @@ -383,220 +376,14 @@ void QGraphicsScenePrivate::init() */ QList QGraphicsScenePrivate::estimateItemsInRect(const QRectF &rect) const { - const_cast(this)->purgeRemovedItems(); const_cast(this)->_q_updateSortCache(); - if (indexMethod != QGraphicsScene::NoIndex) { - // ### Only do this once in a while. - QGraphicsScenePrivate *that = const_cast(this); - - QList items; - // Get items from index - items = that->index->items(rect); - - //### Why there are items indexed and not at some point? - - // Fill in with any unindexed items - foreach (QGraphicsItem *item, linearIndex->items(rect)) { - if (!item->d_ptr->itemDiscovered && item->d_ptr->visible && !(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) { - item->d_ptr->itemDiscovered = 1; - items << item; - } - } - - // Reset the discovered state of all discovered items - for (int i = 0; i < items.size(); ++i) - items.at(i)->d_func()->itemDiscovered = 0; - return items; - } - - QList itemsInRect; - foreach (QGraphicsItem *item, linearIndex->items(rect)) { - if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) - continue; - if (item->d_ptr->visible && item->effectiveOpacity() > qreal(0.0)) - itemsInRect << item; - } + // ### Only do this once in a while. + QGraphicsScenePrivate *that = const_cast(this); - //### Why there are items indexed and not at some point? - - for (int i = 0; i < indexedItems.size(); ++i) { - if (QGraphicsItem *item = indexedItems.at(i)) { - if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) - continue; - if (item->d_ptr->visible && item->effectiveOpacity() > qreal(0.0)) - itemsInRect << item; - } - } + // Get items from index + return that->index->items(rect); - return itemsInRect; -} - -/*! - \internal -*/ -void QGraphicsScenePrivate::addToIndex(QGraphicsItem *item) -{ - if (indexMethod == QGraphicsScene::BspTreeIndex) { - if (item->d_func()->index != -1) { - index->insertItem(item); - foreach (QGraphicsItem *child, item->children()) - child->addToIndex(); - } else { - // The BSP tree is regenerated if the number of items grows to a - // certain threshold, or if the bounding rect of the graph doubles in - // size. - startIndexTimer(); - } - } else if (indexMethod == QGraphicsScene::CustomIndex) { - if (item->d_func()->index != -1) { - index->insertItem(item); - foreach (QGraphicsItem *child, item->children()) - child->addToIndex(); - } - } -} - -/*! - \internal -*/ -void QGraphicsScenePrivate::removeFromIndex(QGraphicsItem *item) -{ - if (indexMethod != QGraphicsScene::NoIndex) { - int index = item->d_func()->index; - if (index != -1) { - this->index->removeItem(item); - freeItemIndexes << index; - indexedItems[index] = 0; - item->d_func()->index = -1; - linearIndex->insertItem(item); - - foreach (QGraphicsItem *child, item->children()) - child->removeFromIndex(); - } - startIndexTimer(); - } -} - -/*! - \internal -*/ -void QGraphicsScenePrivate::resetIndex() -{ - purgeRemovedItems(); - if (indexMethod != QGraphicsScene::NoIndex) { - for (int i = 0; i < indexedItems.size(); ++i) { - if (QGraphicsItem *item = indexedItems.at(i)) { - item->d_ptr->index = -1; - linearIndex->insertItem(item); - } - } - indexedItems.clear(); - freeItemIndexes.clear(); - regenerateIndex = true; - startIndexTimer(); - } -} - -static inline int intmaxlog(int n) -{ - return (n > 0 ? qMax(qCeil(qLn(qreal(n)) / qLn(qreal(2))), 5) : 0); -} - -/*! - \internal -*/ -void QGraphicsScenePrivate::_q_updateIndex() -{ - if (!indexTimerId) - return; - - Q_Q(QGraphicsScene); - q->killTimer(indexTimerId); - indexTimerId = 0; - - purgeRemovedItems(); - - // Add unindexedItems to indexedItems - QRectF unindexedItemsBoundingRect; - foreach (QGraphicsItem *item, linearIndex->indexedItems()) { - unindexedItemsBoundingRect |= item->sceneBoundingRect(); - if (!freeItemIndexes.isEmpty()) { - int freeIndex = freeItemIndexes.takeFirst(); - item->d_func()->index = freeIndex; - indexedItems[freeIndex] = item; - } else { - item->d_func()->index = indexedItems.size(); - indexedItems << item; - } - } - - // Update growing scene rect. - QRectF oldGrowingItemsBoundingRect = growingItemsBoundingRect; - growingItemsBoundingRect |= unindexedItemsBoundingRect; - - // Determine whether we should regenerate the BSP tree. - if (indexMethod == QGraphicsScene::BspTreeIndex) { - QGraphicsSceneBspTree *bspTree = qobject_cast(index); - Q_ASSERT(bspTree); - int depth = bspTree->depth; - if (depth == 0) { - int oldDepth = intmaxlog(lastItemCount); - depth = intmaxlog(indexedItems.size()); - static const int slack = 100; - //### do something better - QGraphicsSceneBspTree *bsp = static_cast(index); - if (bsp->leafCount() == 0 || (oldDepth != depth && qAbs(lastItemCount - indexedItems.size()) > slack)) { - // ### Crude algorithm. - regenerateIndex = true; - } - } - - // Regenerate the tree. - if (regenerateIndex) { - regenerateIndex = false; - //### do something better - QGraphicsSceneBspTree *bsp = static_cast(index); - bsp->initialize(q->sceneRect(), depth); - foreach (QGraphicsItem *item, indexedItems) - linearIndex->insertItem(item); - lastItemCount = indexedItems.size(); - q->update(); - - // Take this opportunity to reset our largest-item counter for - // untransformable items. When the items are inserted into the BSP - // tree, we'll get an accurate calculation. - largestUntransformableItem = QRectF(); - } - } - - // Insert all unindexed items into the tree. - foreach (QGraphicsItem *item, linearIndex->indexedItems()) { - QRectF rect = item->sceneBoundingRect(); - if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) - continue; - - if (indexMethod != QGraphicsScene::NoIndex) - index->insertItem(item); - - // If the item ignores view transformations, update our - // largest-item-counter to ensure that the view can accurately - // discover untransformable items when drawing. - if (item->d_ptr->itemIsUntransformable()) { - QGraphicsItem *topmostUntransformable = item; - while (topmostUntransformable && (topmostUntransformable->d_ptr->ancestorFlags - & QGraphicsItemPrivate::AncestorIgnoresTransformations)) { - topmostUntransformable = topmostUntransformable->parentItem(); - } - // ### Verify that this is the correct largest untransformable rectangle. - largestUntransformableItem |= item->mapToItem(topmostUntransformable, item->boundingRect()).boundingRect(); - } - } - linearIndex->clear(); - - // Notify scene rect changes. - if (!hasSceneRect && growingItemsBoundingRect != oldGrowingItemsBoundingRect) - emit q->sceneRectChanged(growingItemsBoundingRect); } /*! @@ -740,22 +527,8 @@ void QGraphicsScenePrivate::_q_removeItemLater(QGraphicsItem *item) // chain. item->clearFocus(); - int index = item->d_func()->index; - if (index != -1) { - // Important: The index is useless until purgeRemovedItems() is - // called. - indexedItems[index] = (QGraphicsItem *)0; - if (!purgePending) { - purgePending = true; - q->update(); - } - removedItems << item; - } else { - // Recently added items are purged immediately. unindexedItems() never - // contains stale items. - linearIndex->removeItem(item); - q->update(); - } + //We ask for a removing in the index + this->index->removeItem(item, true); // Reset the mouse grabber and focus item data. if (item == focusItem) @@ -806,51 +579,6 @@ void QGraphicsScenePrivate::_q_removeItemLater(QGraphicsItem *item) /*! \internal - - Removes stale pointers from all data structures. -*/ -void QGraphicsScenePrivate::purgeRemovedItems() -{ - Q_Q(QGraphicsScene); - - if (!purgePending && removedItems.isEmpty()) - return; - - // Remove stale items from the BSP tree. - if (indexMethod != QGraphicsScene::NoIndex) { - index->removeItems(removedItems); - } - - // Purge this list. - removedItems.clear(); - freeItemIndexes.clear(); - for (int i = 0; i < indexedItems.size(); ++i) { - if (!indexedItems.at(i)) - freeItemIndexes << i; - } - purgePending = false; - - // No locality info for the items; update the whole scene. - q->update(); -} - -/*! - \internal - - Starts or restarts the timer used for reindexing unindexed items. -*/ -void QGraphicsScenePrivate::startIndexTimer() -{ - Q_Q(QGraphicsScene); - if (indexTimerId) { - restartIndexTimer = true; - } else { - indexTimerId = q->startTimer(QGRAPHICSSCENE_INDEXTIMER_TIMEOUT); - } -} - -/*! - \internal */ void QGraphicsScenePrivate::addPopup(QGraphicsWidget *widget) { @@ -1964,7 +1692,7 @@ void QGraphicsScenePrivate::climbTree(QGraphicsItem *item, int *stackingOrder) void QGraphicsScenePrivate::_q_updateSortCache() { - _q_updateIndex(); + index->updateIndex(); if (!sortCacheEnabled || !updatingSortCache) return; @@ -1974,15 +1702,11 @@ void QGraphicsScenePrivate::_q_updateSortCache() QList topLevels; - for (int i = 0; i < indexedItems.size(); ++i) { - QGraphicsItem *item = indexedItems.at(i); + for (int i = 0; i < index->indexedItems().count(); ++i) { + QGraphicsItem *item = index->indexedItems().at(i); if (item && item->parentItem() == 0) topLevels << item; } - foreach (QGraphicsItem *item, linearIndex->indexedItems()) { - if (item->parentItem() == 0) - topLevels << item; - } qSort(topLevels.begin(), topLevels.end(), qt_closestLeaf); for (int i = 0; i < topLevels.size(); ++i) @@ -2139,8 +1863,8 @@ QGraphicsScene::QGraphicsScene(QObject *parent) QGraphicsScene::QGraphicsScene(const QRectF &sceneRect, QObject *parent) : QObject(*new QGraphicsScenePrivate, parent) { - setSceneRect(sceneRect); d_func()->init(); + setSceneRect(sceneRect); } /*! @@ -2154,8 +1878,8 @@ QGraphicsScene::QGraphicsScene(const QRectF &sceneRect, QObject *parent) QGraphicsScene::QGraphicsScene(qreal x, qreal y, qreal width, qreal height, QObject *parent) : QObject(*new QGraphicsScenePrivate, parent) { - setSceneRect(x, y, width, height); d_func()->init(); + setSceneRect(x, y, width, height); } /*! @@ -2192,8 +1916,8 @@ QGraphicsScene::~QGraphicsScene() QRectF QGraphicsScene::sceneRect() const { Q_D(const QGraphicsScene); - const_cast(d)->_q_updateIndex(); - return d->hasSceneRect ? d->sceneRect : d->growingItemsBoundingRect; + d->index->updateIndex(); + return d->hasSceneRect ? d->index->rect() : d->growingItemsBoundingRect; } void QGraphicsScene::setSceneRect(const QRectF &rect) { @@ -2201,7 +1925,7 @@ void QGraphicsScene::setSceneRect(const QRectF &rect) if (rect != d->sceneRect) { d->hasSceneRect = !rect.isNull(); d->sceneRect = rect; - d->resetIndex(); + d->index->setRect(rect); emit sceneRectChanged(rect); } } @@ -2390,24 +2114,23 @@ void QGraphicsScene::setItemIndexMethod(ItemIndexMethod method) if (d->indexMethod == method) { return; } - d->resetIndex(); if (d->indexMethod == NoIndex && method == BspTreeIndex) { - QGraphicsSceneBspTree *tree = qobject_cast(d->index); + QGraphicsSceneBspTreeIndex *tree = qobject_cast(d->index); if (!tree) { delete d->index; - d->index = new QGraphicsSceneBspTree(this); + d->index = new QGraphicsSceneBspTreeIndex(this); } } if (d->indexMethod == CustomIndex && method == BspTreeIndex) { QGraphicsSceneIndex *oldIndex = d->index; - d->index = new QGraphicsSceneBspTree(this); + d->index = new QGraphicsSceneBspTreeIndex(this); d->index->insertItems(oldIndex->items(oldIndex->rect())); } if (d->indexMethod == CustomIndex && method == NoIndex) { - d->index = new QGraphicsSceneBspTree(this); + d->index = new QGraphicsSceneLinearIndex(this); } d->indexMethod = method; @@ -2424,7 +2147,6 @@ void QGraphicsScene::setSceneIndex(QGraphicsSceneIndex *index) } d->indexMethod = CustomIndex; d->index = index; - index->mscene = this; } } @@ -2469,8 +2191,8 @@ QGraphicsSceneIndex* QGraphicsScene::sceneIndex() const int QGraphicsScene::bspTreeDepth() const { Q_D(const QGraphicsScene); - QGraphicsSceneBspTree *bspTree = qobject_cast(d->index); - return bspTree ? bspTree->depth : 0; + QGraphicsSceneBspTreeIndex *bspTree = qobject_cast(d->index); + return bspTree ? bspTree->bspDepth() : 0; } void QGraphicsScene::setBspTreeDepth(int depth) { @@ -2483,14 +2205,13 @@ void QGraphicsScene::setBspTreeDepth(int depth) return; } - QGraphicsSceneBspTree *bspTree = qobject_cast(d->index); + QGraphicsSceneBspTreeIndex *bspTree = qobject_cast(d->index); if (!bspTree) { qWarning("QGraphicsScene::setBspTreeDepth: can not apply if indexing method is not BSP"); return; } - bspTree->depth = depth; - d->resetIndex(); + bspTree->setBspDepth(depth); } /*! @@ -2543,24 +2264,7 @@ QRectF QGraphicsScene::itemsBoundingRect() const QList QGraphicsScene::items() const { Q_D(const QGraphicsScene); - const_cast(d)->purgeRemovedItems(); - - // If freeItemIndexes is empty, we know there are no holes in indexedItems and - // unindexedItems. - if (d->freeItemIndexes.isEmpty()) { - if (d->linearIndex->indexedItems().isEmpty()) - return d->indexedItems; - return d->indexedItems + d->linearIndex->indexedItems(); - } - - // Rebuild the list of items to avoid holes. ### We could also just - // compress the item lists at this point. - QList itemList; - foreach (QGraphicsItem *item, d->indexedItems + d->linearIndex->indexedItems()) { - if (item) - itemList << item; - } - return itemList; + return d->index->indexedItems(); } /*! @@ -2830,21 +2534,12 @@ void QGraphicsScene::clear() { Q_D(QGraphicsScene); // Recursive descent delete - for (int i = 0; i < d->indexedItems.size(); ++i) { - if (QGraphicsItem *item = d->indexedItems.at(i)) { + for (int i = 0; i < d->index->indexedItems().size(); ++i) { + if (QGraphicsItem *item = d->index->indexedItems().at(i)) { if (!item->parentItem()) delete item; } } - QList unindexedParents; - foreach (QGraphicsItem *item, d->linearIndex->indexedItems()) { - if (!item->parentItem()) - unindexedParents << item; - } - d->linearIndex->clear(); - qDeleteAll(unindexedParents); - d->indexedItems.clear(); - d->freeItemIndexes.clear(); d->lastItemCount = 0; d->index->clear(); d->largestUntransformableItem = QRectF(); @@ -2968,10 +2663,6 @@ void QGraphicsScene::addItem(QGraphicsItem *item) return; } - // Prevent reusing a recently deleted pointer: purge all removed items - // from our lists. - d->purgeRemovedItems(); - // Invalidate any sort caching; arrival of a new item means we need to // resort. d->invalidateSortCache(); @@ -2989,9 +2680,7 @@ void QGraphicsScene::addItem(QGraphicsItem *item) // Indexing requires sceneBoundingRect(), but because \a item might // not be completely constructed at this point, we need to store it in // a temporary list and schedule an indexing for later. - d->linearIndex->insertItem(item); - item->d_func()->index = -1; - d->startIndexTimer(); + d->index->insertItem(item); // Add to list of toplevels if this item is a toplevel. if (!item->d_ptr->parent) @@ -3351,7 +3040,7 @@ void QGraphicsScene::removeItem(QGraphicsItem *item) // Note: This will access item's sceneBoundingRect(), which (as this is // C++) is why we cannot call removeItem() from QGraphicsItem's // destructor. - d->removeFromIndex(item); + d->index->removeItem(item, false); if (item == d->tabFocusFirst) { QGraphicsWidget *widget = static_cast(item); @@ -3371,15 +3060,6 @@ void QGraphicsScene::removeItem(QGraphicsItem *item) d->unregisterTopLevelItem(item); } - // Remove from our item lists. - int index = item->d_func()->index; - if (index != -1) { - d->freeItemIndexes << index; - d->indexedItems[index] = 0; - } else { - d->linearIndex->removeItem(item); - } - // Remove from scene transform cache int transformIndex = item->d_func()->sceneTransformIndex; if (transformIndex != -1) { @@ -3998,16 +3678,6 @@ bool QGraphicsScene::event(QEvent *event) // geometries that do not have an explicit style set. update(); break; - case QEvent::Timer: - if (d->indexTimerId && static_cast(event)->timerId() == d->indexTimerId) { - if (d->restartIndexTimer) { - d->restartIndexTimer = false; - } else { - // this call will kill the timer - d->_q_updateIndex(); - } - } - // Fallthrough intended - support timers in subclasses. default: return QObject::event(event); } diff --git a/src/gui/graphicsview/qgraphicsscene.h b/src/gui/graphicsview/qgraphicsscene.h index bb3cea7..6476b8c 100644 --- a/src/gui/graphicsview/qgraphicsscene.h +++ b/src/gui/graphicsview/qgraphicsscene.h @@ -279,7 +279,6 @@ private: Q_DECLARE_PRIVATE(QGraphicsScene) Q_DISABLE_COPY(QGraphicsScene) - Q_PRIVATE_SLOT(d_func(), void _q_updateIndex()) Q_PRIVATE_SLOT(d_func(), void _q_emitUpdated()) Q_PRIVATE_SLOT(d_func(), void _q_removeItemLater(QGraphicsItem *item)) Q_PRIVATE_SLOT(d_func(), void _q_updateLater()) @@ -292,6 +291,7 @@ private: friend class QGraphicsViewPrivate; friend class QGraphicsWidget; friend class QGraphicsWidgetPrivate; + friend class QGraphicsSceneBspTreeIndex; }; Q_DECLARE_OPERATORS_FOR_FLAGS(QGraphicsScene::SceneLayers) diff --git a/src/gui/graphicsview/qgraphicsscene_bsp.cpp b/src/gui/graphicsview/qgraphicsscene_bsp.cpp index a81b14d..f8fa450 100644 --- a/src/gui/graphicsview/qgraphicsscene_bsp.cpp +++ b/src/gui/graphicsview/qgraphicsscene_bsp.cpp @@ -83,8 +83,8 @@ public: } }; -QGraphicsSceneBspTree::QGraphicsSceneBspTree(QObject *parent) - : QGraphicsSceneIndex(parent), depth(0), leafCnt(0) +QGraphicsSceneBspTree::QGraphicsSceneBspTree() + : leafCnt(0) { insertVisitor = new QGraphicsSceneInsertItemBspTreeVisitor; removeVisitor = new QGraphicsSceneRemoveItemBspTreeVisitor; @@ -100,7 +100,7 @@ QGraphicsSceneBspTree::~QGraphicsSceneBspTree() void QGraphicsSceneBspTree::initialize(const QRectF &rect, int depth) { - sceneRect = rect; + this->rect = rect; leafCnt = 0; nodes.resize((1 << (depth + 1)) - 1); nodes.fill(Node()); @@ -117,29 +117,19 @@ void QGraphicsSceneBspTree::clear() leaves.clear(); } -QRectF QGraphicsSceneBspTree::rect() const -{ - return sceneRect; -} - -void QGraphicsSceneBspTree::setRect(const QRectF &rect) -{ - sceneRect = rect; -} - -void QGraphicsSceneBspTree::insertItem(QGraphicsItem *item) +void QGraphicsSceneBspTree::insertItem(QGraphicsItem *item, const QRectF &rect) { insertVisitor->item = item; - climbTree(insertVisitor, item->sceneBoundingRect()); + climbTree(insertVisitor, rect); } -void QGraphicsSceneBspTree::removeItem(QGraphicsItem *item) +void QGraphicsSceneBspTree::removeItem(QGraphicsItem *item, const QRectF &rect) { removeVisitor->item = item; - climbTree(removeVisitor, item->sceneBoundingRect()); + climbTree(removeVisitor, rect); } -void QGraphicsSceneBspTree::removeItems(const QList &items) +void QGraphicsSceneBspTree::removeItems(const QSet &items) { for (int i = 0; i < leaves.size(); ++i) { QList newItemList; @@ -247,10 +237,8 @@ void QGraphicsSceneBspTree::initialize(const QRectF &rect, int depth, int index) void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QPointF &pos, int index) { - if (nodes.isEmpty()) { - // should never happen for bsp tree internal to QGraphicsScene - initialize(sceneRect, 0); - } + if (nodes.isEmpty()) + return; const Node &node = nodes.at(index); int childIndex = firstChildIndex(index); @@ -279,10 +267,8 @@ void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, con void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QRectF &rect, int index) { - if (nodes.isEmpty()) { - // should never happen for bsp tree internal to QGraphicsScene - initialize(sceneRect, 0); - } + if (nodes.isEmpty()) + return; const Node &node = nodes.at(index); int childIndex = firstChildIndex(index); @@ -316,7 +302,7 @@ void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, con QRectF QGraphicsSceneBspTree::rectForIndex(int index) const { if (index <= 0) - return sceneRect; + return rect; int parentIdx = parentIndex(index); QRectF rect = rectForIndex(parentIdx); diff --git a/src/gui/graphicsview/qgraphicsscene_bsp_p.h b/src/gui/graphicsview/qgraphicsscene_bsp_p.h index 69d9eee..e6ceb78 100644 --- a/src/gui/graphicsview/qgraphicsscene_bsp_p.h +++ b/src/gui/graphicsview/qgraphicsscene_bsp_p.h @@ -60,7 +60,6 @@ #include #include #include -#include QT_BEGIN_NAMESPACE @@ -70,10 +69,8 @@ class QGraphicsSceneInsertItemBspTreeVisitor; class QGraphicsSceneRemoveItemBspTreeVisitor; class QGraphicsSceneFindItemBspTreeVisitor; -class Q_AUTOTEST_EXPORT QGraphicsSceneBspTree : public QGraphicsSceneIndex +class QGraphicsSceneBspTree { - Q_OBJECT - public: struct Node { @@ -85,27 +82,20 @@ public: Type type; }; - QGraphicsSceneBspTree(QObject *parent = 0); + QGraphicsSceneBspTree(); ~QGraphicsSceneBspTree(); void initialize(const QRectF &rect, int depth); void clear(); - QRectF rect() const; - void setRect(const QRectF &rect); - void insertItem(QGraphicsItem *item); - void removeItem(QGraphicsItem *item); - void removeItems(const QList &items); + void insertItem(QGraphicsItem *item, const QRectF &rect); + void removeItem(QGraphicsItem *item, const QRectF &rect); + void removeItems(const QSet &items); - QList items(const QPointF &point); QList items(const QRectF &rect); - + QList items(const QPointF &pos); int leafCount() const; - int depth; - -private: - inline int firstChildIndex(int index) const { return index * 2 + 1; } @@ -114,6 +104,7 @@ private: QString debug(int index) const; +private: void initialize(const QRectF &rect, int depth, int index); void climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QPointF &pos, int index = 0); void climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QRectF &rect, int index = 0); @@ -125,7 +116,7 @@ private: QVector nodes; QVector > leaves; int leafCnt; - QRectF sceneRect; + QRectF rect; QGraphicsSceneInsertItemBspTreeVisitor *insertVisitor; QGraphicsSceneRemoveItemBspTreeVisitor *removeVisitor; @@ -139,8 +130,6 @@ public: virtual void visit(QList *items) = 0; }; -Q_DECLARE_TYPEINFO(QGraphicsSceneBspTree::Node, Q_PRIMITIVE_TYPE); - QT_END_NAMESPACE #endif // QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicsscene_linear_p.h b/src/gui/graphicsview/qgraphicsscene_linear_p.h deleted file mode 100644 index 41e03e4..0000000 --- a/src/gui/graphicsview/qgraphicsscene_linear_p.h +++ /dev/null @@ -1,124 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRAPHICSSCENELINEARINDEX_P_H -#define QGRAPHICSSCENELINEARINDEX_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include - -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -class Q_AUTOTEST_EXPORT QGraphicsSceneLinearIndex : public QGraphicsSceneIndex -{ - Q_OBJECT - -private: - QRectF m_sceneRect; - QList m_items; - -public: - QGraphicsSceneLinearIndex(QObject *parent = 0): QGraphicsSceneIndex(parent) { - } - - virtual void setRect(const QRectF &rect) { - m_sceneRect = rect; - } - - virtual QRectF rect() const { - return m_sceneRect; - } - - virtual void clear() { - m_items.clear(); - } - - virtual void insertItem(QGraphicsItem *item) { - m_items << item; - } - - virtual void removeItem(QGraphicsItem *item) { - m_items.removeAll(item); - } - - virtual QList items(const QPointF &point) { - QList result; - foreach (QGraphicsItem *item, m_items) - if (item->sceneBoundingRect().contains(point)) - result << item; - return result; - } - - virtual QList items(const QRectF &rect) { - QList result; - foreach (QGraphicsItem *item, m_items) - if (item->sceneBoundingRect().intersects(rect)) - result << item; - return result; - } - - QList indexedItems() { - return m_items; - } -}; - -QT_END_NAMESPACE - -#endif // QT_NO_GRAPHICSVIEW - -#endif // QGRAPHICSSCENELINEARINDEX_P_H diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 65c1a69..2c0d464 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -57,8 +57,8 @@ #if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW -#include "qgraphicsscene_bsp_p.h" -#include "qgraphicsscene_linear_p.h" +#include "qgraphicsscenebsptreeindex_p.h" +#include "qgraphicsscenelinearindex_p.h" #include "qgraphicssceneindex.h" #include "qgraphicsitem_p.h" @@ -89,15 +89,10 @@ public: int bspTreeDepth; QList estimateItemsInRect(const QRectF &rect) const; - void addToIndex(QGraphicsItem *item); - void removeFromIndex(QGraphicsItem *item); - void resetIndex(); - void _q_updateIndex(); int lastItemCount; QGraphicsSceneIndex *index; - QGraphicsSceneLinearIndex *linearIndex; QRectF sceneRect; bool hasSceneRect; @@ -112,7 +107,6 @@ public: QPainterPath selectionArea; int selectionChanging; QSet selectedItems; - QList indexedItems; QList dirtyItems; QList pendingUpdateItems; QList unpolishedItems; @@ -127,21 +121,11 @@ public: void resetDirtyItemsLater(); bool dirtyItemResetPending; - QList freeItemIndexes; - bool regenerateIndex; - - bool purgePending; void _q_removeItemLater(QGraphicsItem *item); - QList removedItems; - void purgeRemovedItems(); QBrush backgroundBrush; QBrush foregroundBrush; - int indexTimerId; - bool restartIndexTimer; - void startIndexTimer(); - bool stickyFocus; bool hasFocus; QGraphicsItem *focusItem; diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp new file mode 100644 index 0000000..ebc167a --- /dev/null +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp @@ -0,0 +1,437 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +static const int QGRAPHICSSCENE_INDEXTIMER_TIMEOUT = 2000; + +#include "qgraphicsscenebsptreeindex_p.h" +#include "qgraphicsitem_p.h" +#include "qgraphicsscene_p.h" + +#include + +#include + +QGraphicsSceneBspTreeIndex::QGraphicsSceneBspTreeIndex(QGraphicsScene *scene) + : QGraphicsSceneIndex(scene), + bspTreeDepth(0), + indexTimerId(0), + restartIndexTimer(false), + regenerateIndex(true), + lastItemCount(0), + purgePending(false) +{ + +} + +void QGraphicsSceneBspTreeIndex::setRect(const QRectF &rect) +{ + m_sceneRect = rect; + resetIndex(); +} + +QRectF QGraphicsSceneBspTreeIndex::rect() const +{ + const_cast(this)->updateIndex(); + return m_sceneRect; +} + +void QGraphicsSceneBspTreeIndex::clear() +{ + bsp.clear(); + lastItemCount = 0; + freeItemIndexes.clear(); + m_indexedItems.clear(); + unindexedItems.clear(); +} + +void QGraphicsSceneBspTreeIndex::insertItem(QGraphicsItem *item) +{ + // Prevent reusing a recently deleted pointer: purge all removed items + // from our lists. + purgeRemovedItems(); + + // Indexing requires sceneBoundingRect(), but because \a item might + // not be completely constructed at this point, we need to store it in + // a temporary list and schedule an indexing for later. + unindexedItems << item; + item->d_func()->index = -1; + startIndexTimer(); +} + +/*! + \internal +*/ +void QGraphicsSceneBspTreeIndex::addToIndex(QGraphicsItem *item) +{ + if (item->d_func()->index != -1) { + bsp.insertItem(item, item->sceneBoundingRect()); + foreach (QGraphicsItem *child, item->children()) + child->addToIndex(); + } else { + // The BSP tree is regenerated if the number of items grows to a + // certain threshold, or if the bounding rect of the graph doubles in + // size. + startIndexTimer(); + } +} + +void QGraphicsSceneBspTreeIndex::removeItem(QGraphicsItem *item, bool itemIsAboutToDie) +{ + if (!itemIsAboutToDie) { + // Note: This will access item's sceneBoundingRect(), which (as this is + // C++) is why we cannot call removeItem() from QGraphicsItem's + // destructor. + removeFromIndex(item); + + // Remove from our item lists. + int index = item->d_func()->index; + if (index != -1) { + freeItemIndexes << index; + m_indexedItems[index] = 0; + } else { + unindexedItems.removeAll(item); + } + + } else { + int index = item->d_func()->index; + if (index != -1) { + // Important: The index is useless until purgeRemovedItems() is + // called. + m_indexedItems[index] = (QGraphicsItem *)0; + if (!purgePending) { + purgePending = true; + scene()->update(); + } + removedItems << item; + } else { + // Recently added items are purged immediately. unindexedItems() never + // contains stale items. + unindexedItems.removeAll(item); + scene()->update(); + } + } +} +/*! + \internal +*/ +void QGraphicsSceneBspTreeIndex::removeFromIndex(QGraphicsItem *item) +{ + if (item->d_func()->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) { + // ### remove from child index only if applicable + return; + } + int index = item->d_func()->index; + if (index != -1) { + bsp.removeItem(item, item->sceneBoundingRect()); + freeItemIndexes << index; + m_indexedItems[index] = 0; + item->d_func()->index = -1; + unindexedItems << item; + + //prepareGeometryChange will call updateItem + foreach (QGraphicsItem *child, item->children()) + child->prepareGeometryChange(); + } + startIndexTimer(); +} + +void QGraphicsSceneBspTreeIndex::updateItem(QGraphicsItem *item) +{ + // Note: This will access item's sceneBoundingRect(), which (as this is + // C++) is why we cannot call removeItem() from QGraphicsItem's + // destructor. + removeFromIndex(item); +} + +QList QGraphicsSceneBspTreeIndex::items(const QPointF &point) +{ + purgeRemovedItems(); + QList rectItems = bsp.items(QRectF(point, QSizeF(1, 1))); + // Fill in with any unindexed items + for (int i = 0; i < unindexedItems.size(); ++i) { + if (QGraphicsItem *item = unindexedItems.at(i)) { + if (!item->d_ptr->itemDiscovered && item->d_ptr->visible && !(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) { + QRectF boundingRect = item->sceneBoundingRect(); + if (boundingRect.intersects(QRectF(point, QSizeF(1, 1)))) { + item->d_ptr->itemDiscovered = 1; + rectItems << item; + } + } + } + } + + // Reset the discovered state of all discovered items + for (int i = 0; i < rectItems.size(); ++i) + rectItems.at(i)->d_func()->itemDiscovered = 0; + + return rectItems; +} + +QList QGraphicsSceneBspTreeIndex::items(const QRectF &rect) +{ + purgeRemovedItems(); + QList rectItems = bsp.items(rect); + // Fill in with any unindexed items + for (int i = 0; i < unindexedItems.size(); ++i) { + if (QGraphicsItem *item = unindexedItems.at(i)) { + if (!item->d_ptr->itemDiscovered && item->d_ptr->visible && !(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) { + QRectF boundingRect = item->sceneBoundingRect(); + if (boundingRect.intersects(rect)) { + item->d_ptr->itemDiscovered = 1; + rectItems << item; + } + } + } + } + + // Reset the discovered state of all discovered items + for (int i = 0; i < rectItems.size(); ++i) + rectItems.at(i)->d_func()->itemDiscovered = 0; + + return rectItems; +} + +QList QGraphicsSceneBspTreeIndex::indexedItems() +{ + purgeRemovedItems(); + // If freeItemIndexes is empty, we know there are no holes in indexedItems and + // unindexedItems. + if (freeItemIndexes.isEmpty()) { + if (unindexedItems.isEmpty()) + return m_indexedItems; + return m_indexedItems + unindexedItems; + } + + // Rebuild the list of items to avoid holes. ### We could also just + // compress the item lists at this point. + QList itemList; + foreach (QGraphicsItem *item, m_indexedItems + unindexedItems) { + if (item) + itemList << item; + } + return itemList; +} + +void QGraphicsSceneBspTreeIndex::updateIndex() +{ + _q_updateIndex(); +} + +int QGraphicsSceneBspTreeIndex::bspDepth() +{ + return bspTreeDepth; +} + +void QGraphicsSceneBspTreeIndex::setBspDepth(int depth) +{ + bspTreeDepth = depth; + resetIndex(); +} + +bool QGraphicsSceneBspTreeIndex::event(QEvent *event) +{ + switch (event->type()) { + case QEvent::Timer: + if (indexTimerId && static_cast(event)->timerId() == indexTimerId) { + if (restartIndexTimer) { + restartIndexTimer = false; + } else { + // this call will kill the timer + _q_updateIndex(); + } + } + // Fallthrough intended - support timers in subclasses. + default: + return QObject::event(event); + } + return true; +} + +static inline int intmaxlog(int n) +{ + return (n > 0 ? qMax(qCeil(qLn(qreal(n)) / qLn(qreal(2))), 5) : 0); +} + +/*! + \internal +*/ +void QGraphicsSceneBspTreeIndex::_q_updateIndex() +{ + if (!indexTimerId) + return; + + killTimer(indexTimerId); + indexTimerId = 0; + + purgeRemovedItems(); + + // Add unindexedItems to indexedItems + QRectF unindexedItemsBoundingRect; + for (int i = 0; i < unindexedItems.size(); ++i) { + if (QGraphicsItem *item = unindexedItems.at(i)) { + unindexedItemsBoundingRect |= item->sceneBoundingRect(); + if (!freeItemIndexes.isEmpty()) { + int freeIndex = freeItemIndexes.takeFirst(); + item->d_func()->index = freeIndex; + m_indexedItems[freeIndex] = item; + } else { + item->d_func()->index = m_indexedItems.size(); + m_indexedItems << item; + } + } + } + + // Update growing scene rect. + QRectF oldGrowingItemsBoundingRect = scene()->d_func()->growingItemsBoundingRect; + scene()->d_func()->growingItemsBoundingRect |= unindexedItemsBoundingRect; + + // Determine whether we should regenerate the BSP tree. + if (bspTreeDepth == 0) { + int oldDepth = intmaxlog(lastItemCount); + bspTreeDepth = intmaxlog(m_indexedItems.size()); + static const int slack = 100; + if (bsp.leafCount() == 0 || (oldDepth != bspTreeDepth && qAbs(lastItemCount - m_indexedItems.size()) > slack)) { + // ### Crude algorithm. + regenerateIndex = true; + } + } + + // Regenerate the tree. + if (regenerateIndex) { + regenerateIndex = false; + bsp.initialize(scene()->sceneRect(), bspTreeDepth); + unindexedItems = m_indexedItems; + lastItemCount = m_indexedItems.size(); + scene()->update(); + + // Take this opportunity to reset our largest-item counter for + // untransformable items. When the items are inserted into the BSP + // tree, we'll get an accurate calculation. + scene()->d_func()->largestUntransformableItem = QRectF(); + } + + // Insert all unindexed items into the tree. + for (int i = 0; i < unindexedItems.size(); ++i) { + if (QGraphicsItem *item = unindexedItems.at(i)) { + QRectF rect = item->sceneBoundingRect(); + if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) + continue; + + bsp.insertItem(item,rect); + + // If the item ignores view transformations, update our + // largest-item-counter to ensure that the view can accurately + // discover untransformable items when drawing. + if (item->d_ptr->itemIsUntransformable()) { + QGraphicsItem *topmostUntransformable = item; + while (topmostUntransformable && (topmostUntransformable->d_ptr->ancestorFlags + & QGraphicsItemPrivate::AncestorIgnoresTransformations)) { + topmostUntransformable = topmostUntransformable->parentItem(); + } + // ### Verify that this is the correct largest untransformable rectangle. + scene()->d_func()->largestUntransformableItem |= item->mapToItem(topmostUntransformable, item->boundingRect()).boundingRect(); + } + } + } + unindexedItems.clear(); + + // Notify scene rect changes. + if (!scene()->d_func()->hasSceneRect && scene()->d_func()->growingItemsBoundingRect != oldGrowingItemsBoundingRect) + emit scene()->sceneRectChanged(scene()->d_func()->growingItemsBoundingRect); +} + + +/*! + \internal + + Removes stale pointers from all data structures. +*/ +void QGraphicsSceneBspTreeIndex::purgeRemovedItems() +{ + if (!purgePending && removedItems.isEmpty()) + return; + + // Remove stale items from the BSP tree. + bsp.removeItems(removedItems.toSet()); + // Purge this list. + removedItems.clear(); + freeItemIndexes.clear(); + for (int i = 0; i < m_indexedItems.size(); ++i) { + if (!m_indexedItems.at(i)) + freeItemIndexes << i; + } + purgePending = false; + + // No locality info for the items; update the whole scene. + scene()->update(); +} + +/*! + \internal + + Starts or restarts the timer used for reindexing unindexed items. +*/ +void QGraphicsSceneBspTreeIndex::startIndexTimer() +{ + if (indexTimerId) { + restartIndexTimer = true; + } else { + indexTimerId = startTimer(QGRAPHICSSCENE_INDEXTIMER_TIMEOUT); + } +} + +/*! + \internal +*/ +void QGraphicsSceneBspTreeIndex::resetIndex() +{ + purgeRemovedItems(); + for (int i = 0; i < m_indexedItems.size(); ++i) { + if (QGraphicsItem *item = m_indexedItems.at(i)) { + item->d_ptr->index = -1; + unindexedItems << item; + } + } + m_indexedItems.clear(); + freeItemIndexes.clear(); + regenerateIndex = true; + startIndexTimer(); +} diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h new file mode 100644 index 0000000..74af910 --- /dev/null +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h @@ -0,0 +1,118 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#ifndef QGRAPHICSBSPTREEINDEX_H +#define QGRAPHICSBSPTREEINDEX_H + +#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW + +QT_BEGIN_NAMESPACE + +#include +#include +#include +#include +#include + +#include "qgraphicsscene_bsp_p.h" + +class Q_AUTOTEST_EXPORT QGraphicsSceneBspTreeIndex : public QGraphicsSceneIndex +{ + Q_OBJECT +public: + QGraphicsSceneBspTreeIndex(QGraphicsScene *scene = 0); + + void setRect(const QRectF &rect); + virtual QRectF rect() const; + + void clear(); + + void insertItem(QGraphicsItem *item); + void removeItem(QGraphicsItem *item, bool itemIsAboutToDie); + void updateItem(QGraphicsItem *item); + + QList items(const QPointF &point); + QList items(const QRectF &rect); + + QList indexedItems(); + + void updateIndex(); + + int bspDepth(); + void setBspDepth(int depth); + +protected: + bool event(QEvent *event); + +public slots : + void _q_updateIndex(); + +private : + QGraphicsSceneBspTree bsp; + QRectF m_sceneRect; + int bspTreeDepth; + int indexTimerId; + bool restartIndexTimer; + bool regenerateIndex; + int lastItemCount; + + QList m_indexedItems; + QList unindexedItems; + QList freeItemIndexes; + + bool purgePending; + QList removedItems; + void purgeRemovedItems(); + + void startIndexTimer(); + void resetIndex(); + + void addToIndex(QGraphicsItem *item); + void removeFromIndex(QGraphicsItem *item); +}; + +QT_END_NAMESPACE + +#endif // QT_NO_GRAPHICSVIEW + +#endif // QGRAPHICSBSPTREEINDEX_H diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index 904e0af..7360bed 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -49,7 +49,7 @@ QT_BEGIN_NAMESPACE /*! Constructs an abstract scene index. */ -QGraphicsSceneIndex::QGraphicsSceneIndex(QObject *parent): QObject(parent) +QGraphicsSceneIndex::QGraphicsSceneIndex(QGraphicsScene *scene): QObject(scene), m_scene(scene) { } @@ -108,7 +108,7 @@ QGraphicsSceneIndex::~QGraphicsSceneIndex() */ QGraphicsScene* QGraphicsSceneIndex::scene() { - return mscene; + return m_scene; } /*! @@ -121,7 +121,7 @@ QGraphicsScene* QGraphicsSceneIndex::scene() */ void QGraphicsSceneIndex::updateItem(QGraphicsItem *item) { - removeItem(item); + removeItem(item,false); insertItem(item); } @@ -145,10 +145,10 @@ void QGraphicsSceneIndex::insertItems(const QList &items) \sa removeItem(), removeItems(), updateItems() */ -void QGraphicsSceneIndex::removeItems(const QList &items) +void QGraphicsSceneIndex::removeItems(const QList &items, bool itemsAreAboutToDie) { foreach (QGraphicsItem *item, items) - removeItem(item); + removeItem(item,itemsAreAboutToDie); } /*! @@ -164,6 +164,10 @@ void QGraphicsSceneIndex::updateItems(const QList &items) updateItem(item); } +void QGraphicsSceneIndex::updateIndex() +{ +} + QT_END_NAMESPACE #include "moc_qgraphicssceneindex.cpp" diff --git a/src/gui/graphicsview/qgraphicssceneindex.h b/src/gui/graphicsview/qgraphicssceneindex.h index d3b6c9f..3b034d4 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.h +++ b/src/gui/graphicsview/qgraphicssceneindex.h @@ -64,27 +64,32 @@ class Q_GUI_EXPORT QGraphicsSceneIndex: public QObject Q_OBJECT public: - QGraphicsSceneIndex(QObject *parent = 0); + QGraphicsSceneIndex(QGraphicsScene *scene = 0); virtual ~QGraphicsSceneIndex(); + QGraphicsScene* scene(); + virtual void setRect(const QRectF &rect) = 0; virtual QRectF rect() const = 0; virtual void clear() = 0; virtual void insertItem(QGraphicsItem *item) = 0; - virtual void removeItem(QGraphicsItem *item) = 0; + virtual void removeItem(QGraphicsItem *items, bool itemIsAboutToDie) = 0; virtual void updateItem(QGraphicsItem *item); virtual void insertItems(const QList &items); - virtual void removeItems(const QList &items); + virtual void removeItems(const QList &items, bool itemsAreAboutToDie); virtual void updateItems(const QList &items); virtual QList items(const QPointF &point) = 0; virtual QList items(const QRectF &rect) = 0; - QGraphicsScene* scene(); + virtual QList indexedItems() = 0; + + virtual void updateIndex(); - QGraphicsScene* mscene; +private: + QGraphicsScene *m_scene; }; #endif // QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicsscenelinearindex_p.h b/src/gui/graphicsview/qgraphicsscenelinearindex_p.h new file mode 100644 index 0000000..30948d9 --- /dev/null +++ b/src/gui/graphicsview/qgraphicsscenelinearindex_p.h @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGRAPHICSSCENELINEARINDEX_P_H +#define QGRAPHICSSCENELINEARINDEX_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + +#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class Q_AUTOTEST_EXPORT QGraphicsSceneLinearIndex : public QGraphicsSceneIndex +{ + Q_OBJECT + +private: + QRectF m_sceneRect; + QList m_items; + +public: + QGraphicsSceneLinearIndex(QGraphicsScene *scene = 0): QGraphicsSceneIndex(scene) + { + } + + virtual void setRect(const QRectF &rect) { + m_sceneRect = rect; + } + + virtual QRectF rect() const { + return m_sceneRect; + } + + virtual void clear() { + m_items.clear(); + } + + virtual void insertItem(QGraphicsItem *item) { + m_items << item; + } + + virtual void removeItem(QGraphicsItem *item, bool itemIsAboutToDie) { + Q_UNUSED(itemIsAboutToDie); + m_items.removeAll(item); + } + + virtual QList items(const QPointF &point) { + QList result; + foreach (QGraphicsItem *item, m_items) + if (item->sceneBoundingRect().contains(point)) + result << item; + return result; + } + + virtual QList items(const QRectF &rect) { + QList result; + foreach (QGraphicsItem *item, m_items) + if (item->sceneBoundingRect().intersects(rect)) + result << item; + return result; + } + + QList indexedItems() { + return m_items; + } +}; + +QT_END_NAMESPACE + +#endif // QT_NO_GRAPHICSVIEW + +#endif // QGRAPHICSSCENELINEARINDEX_P_H diff --git a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp index 955f2d3..3dca152 100644 --- a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp +++ b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp @@ -43,8 +43,8 @@ #include #include #include -#include -#include +#include +#include //TESTED_CLASS= @@ -88,12 +88,12 @@ void tst_QGraphicsSceneIndex::common_data() QGraphicsSceneIndex *tst_QGraphicsSceneIndex::createIndex(const QString &indexMethod) { QGraphicsSceneIndex *index = 0; - + QGraphicsScene *scene = new QGraphicsScene(); if (indexMethod == "bsp") - index = new QGraphicsSceneBspTree; + index = new QGraphicsSceneBspTreeIndex(scene); if (indexMethod == "linear") - index = new QGraphicsSceneLinearIndex; + index = new QGraphicsSceneLinearIndex(scene); return index; } @@ -104,8 +104,9 @@ void tst_QGraphicsSceneIndex::sceneRect_data() } void tst_QGraphicsSceneIndex::sceneRect() -{ - QGraphicsSceneIndex *index = new QGraphicsSceneBspTree; +{ + QGraphicsScene *scene = new QGraphicsScene(); + QGraphicsSceneIndex *index = new QGraphicsSceneBspTreeIndex(scene); index->setRect(QRectF(0, 0, 2000, 2000)); QCOMPARE(index->rect(), QRectF(0, 0, 2000, 2000)); } -- cgit v0.12 From 7d39e871e679be8afc10c7109a5cc396ead886f7 Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Tue, 5 May 2009 17:56:43 +0200 Subject: Fix deletion of indexed items, and fix comments. It was not a good idea to delete all items in the middle of the loop when clearing the scene since we change the content of indexedItems by deleting one of them. We need to store first all top level items in a temporary list and then delete them in one shot (that will delete their children as well). --- src/gui/graphicsview/qgraphicsscene.cpp | 9 +++++---- tests/auto/qgraphicslayout/tst_qgraphicslayout.cpp | 1 - 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index e9fad68..f2e5f57 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -2549,13 +2549,16 @@ void QGraphicsScene::clearSelection() void QGraphicsScene::clear() { Q_D(QGraphicsScene); + QList items; // Recursive descent delete for (int i = 0; i < d->index->indexedItems().size(); ++i) { if (QGraphicsItem *item = d->index->indexedItems().at(i)) { if (!item->parentItem()) - delete item; + items << item; } } + //We delete all top level items + qDeleteAll(items); d->lastItemCount = 0; d->index->clear(); d->largestUntransformableItem = QRectF(); @@ -2693,9 +2696,7 @@ void QGraphicsScene::addItem(QGraphicsItem *item) // Add the item to this scene item->d_func()->scene = targetScene; - // Indexing requires sceneBoundingRect(), but because \a item might - // not be completely constructed at this point, we need to store it in - // a temporary list and schedule an indexing for later. + // Add the item in the index d->index->insertItem(item); // Add to list of toplevels if this item is a toplevel. diff --git a/tests/auto/qgraphicslayout/tst_qgraphicslayout.cpp b/tests/auto/qgraphicslayout/tst_qgraphicslayout.cpp index f2a6bfd..617790c 100644 --- a/tests/auto/qgraphicslayout/tst_qgraphicslayout.cpp +++ b/tests/auto/qgraphicslayout/tst_qgraphicslayout.cpp @@ -687,7 +687,6 @@ void tst_QGraphicsLayout::ownership() delete top; //don't crash after that. } - } QTEST_MAIN(tst_QGraphicsLayout) -- cgit v0.12 From 560ca373e4879f335a0ceeb3f8a769cc0e4297fe Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Wed, 6 May 2009 10:16:51 +0200 Subject: Make const when it needs to be. --- src/gui/graphicsview/qgraphicssceneindex.cpp | 4 ++-- src/gui/graphicsview/qgraphicssceneindex.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index 7360bed..86a2fbb 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -104,9 +104,9 @@ QGraphicsSceneIndex::~QGraphicsSceneIndex() */ /*! - Returns the scene of this scene index. + Returns the scene of this index. */ -QGraphicsScene* QGraphicsSceneIndex::scene() +QGraphicsScene* QGraphicsSceneIndex::scene() const { return m_scene; } diff --git a/src/gui/graphicsview/qgraphicssceneindex.h b/src/gui/graphicsview/qgraphicssceneindex.h index 3b034d4..a782323 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.h +++ b/src/gui/graphicsview/qgraphicssceneindex.h @@ -67,7 +67,7 @@ public: QGraphicsSceneIndex(QGraphicsScene *scene = 0); virtual ~QGraphicsSceneIndex(); - QGraphicsScene* scene(); + QGraphicsScene* scene() const; virtual void setRect(const QRectF &rect) = 0; virtual QRectF rect() const = 0; -- cgit v0.12 From 210bd7b6033e41aad61fe131002dc5e496d7427a Mon Sep 17 00:00:00 2001 From: Tobias Koenig Date: Sat, 16 May 2009 12:15:40 +0200 Subject: Extended QRegExp by a W3C XML Schema mode --- src/corelib/tools/qregexp.cpp | 330 +++++++++++++++++++++++++++++++++++++++++- src/corelib/tools/qregexp.h | 2 +- 2 files changed, 329 insertions(+), 3 deletions(-) diff --git a/src/corelib/tools/qregexp.cpp b/src/corelib/tools/qregexp.cpp index e1c3921..f69a99f 100644 --- a/src/corelib/tools/qregexp.cpp +++ b/src/corelib/tools/qregexp.cpp @@ -70,6 +70,8 @@ int qFindString(const QChar *haystack, int haystackLen, int from, #define RXERR_LEFTDELIM QT_TRANSLATE_NOOP("QRegExp", "missing left delim") #define RXERR_END QT_TRANSLATE_NOOP("QRegExp", "unexpected end") #define RXERR_LIMIT QT_TRANSLATE_NOOP("QRegExp", "met internal limit") +#define RXERR_INTERVAL QT_TRANSLATE_NOOP("QRegExp", "invalid interval") +#define RXERR_CATEGORY QT_TRANSLATE_NOOP("QRegExp", "invalid category") /* WARNING! Be sure to read qregexp.tex before modifying this file. @@ -1116,6 +1118,7 @@ private: bool valid; // is the regular expression valid? Qt::CaseSensitivity cs; // case sensitive? bool greedyQuantifiers; // RegExp2? + bool xmlSchemaExtensions; #ifndef QT_NO_REGEXP_BACKREF int nbrefs; // number of back-references #endif @@ -1193,6 +1196,8 @@ private: friend class Box; + void setupCategoriesRangeMap(); + /* This is the lexical analyzer for regular expressions. */ @@ -1232,6 +1237,7 @@ private: int yyTok; // the last token read bool yyMayCapture; // set this to false to disable capturing + QHash > categoriesRangeMap; // fast lookup hash for xml schema extensions friend struct QRegExpMatchState; }; @@ -1253,7 +1259,8 @@ struct QRegExpLookahead #endif QRegExpEngine::QRegExpEngine(const QRegExpEngineKey &key) - : cs(key.cs), greedyQuantifiers(key.patternSyntax == QRegExp::RegExp2) + : cs(key.cs), greedyQuantifiers(key.patternSyntax == QRegExp::RegExp2), + xmlSchemaExtensions(false) { setup(); @@ -1268,6 +1275,8 @@ QRegExpEngine::QRegExpEngine(const QRegExpEngineKey &key) case QRegExp::FixedString: rx = QRegExp::escape(key.pattern); break; + case QRegExp::W3CXmlSchema11: + xmlSchemaExtensions = true; default: rx = key.pattern; } @@ -2621,6 +2630,152 @@ void QRegExpEngine::Box::addAnchorsToEngine(const Box &to) const } } +void QRegExpEngine::setupCategoriesRangeMap() +{ + categoriesRangeMap.insert("IsBasicLatin", qMakePair(0x0000, 0x007F)); + categoriesRangeMap.insert("IsLatin-1Supplement", qMakePair(0x0080, 0x00FF)); + categoriesRangeMap.insert("IsLatinExtended-A", qMakePair(0x0100, 0x017F)); + categoriesRangeMap.insert("IsLatinExtended-B", qMakePair(0x0180, 0x024F)); + categoriesRangeMap.insert("IsIPAExtensions", qMakePair(0x0250, 0x02AF)); + categoriesRangeMap.insert("IsSpacingModifierLetters", qMakePair(0x02B0, 0x02FF)); + categoriesRangeMap.insert("IsCombiningDiacriticalMarks", qMakePair(0x0300, 0x036F)); + categoriesRangeMap.insert("IsGreek", qMakePair(0x0370, 0x03FF)); + categoriesRangeMap.insert("IsCyrillic", qMakePair(0x0400, 0x04FF)); + categoriesRangeMap.insert("IsCyrillicSupplement", qMakePair(0x0500, 0x052F)); + categoriesRangeMap.insert("IsArmenian", qMakePair(0x0530, 0x058F)); + categoriesRangeMap.insert("IsHebrew", qMakePair(0x0590, 0x05FF)); + categoriesRangeMap.insert("IsArabic", qMakePair(0x0600, 0x06FF)); + categoriesRangeMap.insert("IsSyriac", qMakePair(0x0700, 0x074F)); + categoriesRangeMap.insert("IsArabicSupplement", qMakePair(0x0750, 0x077F)); + categoriesRangeMap.insert("IsThaana", qMakePair(0x0780, 0x07BF)); + categoriesRangeMap.insert("IsDevanagari", qMakePair(0x0900, 0x097F)); + categoriesRangeMap.insert("IsBengali", qMakePair(0x0980, 0x09FF)); + categoriesRangeMap.insert("IsGurmukhi", qMakePair(0x0A00, 0x0A7F)); + categoriesRangeMap.insert("IsGujarati", qMakePair(0x0A80, 0x0AFF)); + categoriesRangeMap.insert("IsOriya", qMakePair(0x0B00, 0x0B7F)); + categoriesRangeMap.insert("IsTamil", qMakePair(0x0B80, 0x0BFF)); + categoriesRangeMap.insert("IsTelugu", qMakePair(0x0C00, 0x0C7F)); + categoriesRangeMap.insert("IsKannada", qMakePair(0x0C80, 0x0CFF)); + categoriesRangeMap.insert("IsMalayalam", qMakePair(0x0D00, 0x0D7F)); + categoriesRangeMap.insert("IsSinhala", qMakePair(0x0D80, 0x0DFF)); + categoriesRangeMap.insert("IsThai", qMakePair(0x0E00, 0x0E7F)); + categoriesRangeMap.insert("IsLao", qMakePair(0x0E80, 0x0EFF)); + categoriesRangeMap.insert("IsTibetan", qMakePair(0x0F00, 0x0FFF)); + categoriesRangeMap.insert("IsMyanmar", qMakePair(0x1000, 0x109F)); + categoriesRangeMap.insert("IsGeorgian", qMakePair(0x10A0, 0x10FF)); + categoriesRangeMap.insert("IsHangulJamo", qMakePair(0x1100, 0x11FF)); + categoriesRangeMap.insert("IsEthiopic", qMakePair(0x1200, 0x137F)); + categoriesRangeMap.insert("IsEthiopicSupplement", qMakePair(0x1380, 0x139F)); + categoriesRangeMap.insert("IsCherokee", qMakePair(0x13A0, 0x13FF)); + categoriesRangeMap.insert("IsUnifiedCanadianAboriginalSyllabics", qMakePair(0x1400, 0x167F)); + categoriesRangeMap.insert("IsOgham", qMakePair(0x1680, 0x169F)); + categoriesRangeMap.insert("IsRunic", qMakePair(0x16A0, 0x16FF)); + categoriesRangeMap.insert("IsTagalog", qMakePair(0x1700, 0x171F)); + categoriesRangeMap.insert("IsHanunoo", qMakePair(0x1720, 0x173F)); + categoriesRangeMap.insert("IsBuhid", qMakePair(0x1740, 0x175F)); + categoriesRangeMap.insert("IsTagbanwa", qMakePair(0x1760, 0x177F)); + categoriesRangeMap.insert("IsKhmer", qMakePair(0x1780, 0x17FF)); + categoriesRangeMap.insert("IsMongolian", qMakePair(0x1800, 0x18AF)); + categoriesRangeMap.insert("IsLimbu", qMakePair(0x1900, 0x194F)); + categoriesRangeMap.insert("IsTaiLe", qMakePair(0x1950, 0x197F)); + categoriesRangeMap.insert("IsNewTaiLue", qMakePair(0x1980, 0x19DF)); + categoriesRangeMap.insert("IsKhmerSymbols", qMakePair(0x19E0, 0x19FF)); + categoriesRangeMap.insert("IsBuginese", qMakePair(0x1A00, 0x1A1F)); + categoriesRangeMap.insert("IsPhoneticExtensions", qMakePair(0x1D00, 0x1D7F)); + categoriesRangeMap.insert("IsPhoneticExtensionsSupplement", qMakePair(0x1D80, 0x1DBF)); + categoriesRangeMap.insert("IsCombiningDiacriticalMarksSupplement", qMakePair(0x1DC0, 0x1DFF)); + categoriesRangeMap.insert("IsLatinExtendedAdditional", qMakePair(0x1E00, 0x1EFF)); + categoriesRangeMap.insert("IsGreekExtended", qMakePair(0x1F00, 0x1FFF)); + categoriesRangeMap.insert("IsGeneralPunctuation", qMakePair(0x2000, 0x206F)); + categoriesRangeMap.insert("IsSuperscriptsandSubscripts", qMakePair(0x2070, 0x209F)); + categoriesRangeMap.insert("IsCurrencySymbols", qMakePair(0x20A0, 0x20CF)); + categoriesRangeMap.insert("IsCombiningMarksforSymbols", qMakePair(0x20D0, 0x20FF)); + categoriesRangeMap.insert("IsLetterlikeSymbols", qMakePair(0x2100, 0x214F)); + categoriesRangeMap.insert("IsNumberForms", qMakePair(0x2150, 0x218F)); + categoriesRangeMap.insert("IsArrows", qMakePair(0x2190, 0x21FF)); + categoriesRangeMap.insert("IsMathematicalOperators", qMakePair(0x2200, 0x22FF)); + categoriesRangeMap.insert("IsMiscellaneousTechnical", qMakePair(0x2300, 0x23FF)); + categoriesRangeMap.insert("IsControlPictures", qMakePair(0x2400, 0x243F)); + categoriesRangeMap.insert("IsOpticalCharacterRecognition", qMakePair(0x2440, 0x245F)); + categoriesRangeMap.insert("IsEnclosedAlphanumerics", qMakePair(0x2460, 0x24FF)); + categoriesRangeMap.insert("IsBoxDrawing", qMakePair(0x2500, 0x257F)); + categoriesRangeMap.insert("IsBlockElements", qMakePair(0x2580, 0x259F)); + categoriesRangeMap.insert("IsGeometricShapes", qMakePair(0x25A0, 0x25FF)); + categoriesRangeMap.insert("IsMiscellaneousSymbols", qMakePair(0x2600, 0x26FF)); + categoriesRangeMap.insert("IsDingbats", qMakePair(0x2700, 0x27BF)); + categoriesRangeMap.insert("IsMiscellaneousMathematicalSymbols-A", qMakePair(0x27C0, 0x27EF)); + categoriesRangeMap.insert("IsSupplementalArrows-A", qMakePair(0x27F0, 0x27FF)); + categoriesRangeMap.insert("IsBraillePatterns", qMakePair(0x2800, 0x28FF)); + categoriesRangeMap.insert("IsSupplementalArrows-B", qMakePair(0x2900, 0x297F)); + categoriesRangeMap.insert("IsMiscellaneousMathematicalSymbols-B", qMakePair(0x2980, 0x29FF)); + categoriesRangeMap.insert("IsSupplementalMathematicalOperators", qMakePair(0x2A00, 0x2AFF)); + categoriesRangeMap.insert("IsMiscellaneousSymbolsandArrows", qMakePair(0x2B00, 0x2BFF)); + categoriesRangeMap.insert("IsGlagolitic", qMakePair(0x2C00, 0x2C5F)); + categoriesRangeMap.insert("IsCoptic", qMakePair(0x2C80, 0x2CFF)); + categoriesRangeMap.insert("IsGeorgianSupplement", qMakePair(0x2D00, 0x2D2F)); + categoriesRangeMap.insert("IsTifinagh", qMakePair(0x2D30, 0x2D7F)); + categoriesRangeMap.insert("IsEthiopicExtended", qMakePair(0x2D80, 0x2DDF)); + categoriesRangeMap.insert("IsSupplementalPunctuation", qMakePair(0x2E00, 0x2E7F)); + categoriesRangeMap.insert("IsCJKRadicalsSupplement", qMakePair(0x2E80, 0x2EFF)); + categoriesRangeMap.insert("IsKangxiRadicals", qMakePair(0x2F00, 0x2FDF)); + categoriesRangeMap.insert("IsIdeographicDescriptionCharacters", qMakePair(0x2FF0, 0x2FFF)); + categoriesRangeMap.insert("IsCJKSymbolsandPunctuation", qMakePair(0x3000, 0x303F)); + categoriesRangeMap.insert("IsHiragana", qMakePair(0x3040, 0x309F)); + categoriesRangeMap.insert("IsKatakana", qMakePair(0x30A0, 0x30FF)); + categoriesRangeMap.insert("IsBopomofo", qMakePair(0x3100, 0x312F)); + categoriesRangeMap.insert("IsHangulCompatibilityJamo", qMakePair(0x3130, 0x318F)); + categoriesRangeMap.insert("IsKanbun", qMakePair(0x3190, 0x319F)); + categoriesRangeMap.insert("IsBopomofoExtended", qMakePair(0x31A0, 0x31BF)); + categoriesRangeMap.insert("IsCJKStrokes", qMakePair(0x31C0, 0x31EF)); + categoriesRangeMap.insert("IsKatakanaPhoneticExtensions", qMakePair(0x31F0, 0x31FF)); + categoriesRangeMap.insert("IsEnclosedCJKLettersandMonths", qMakePair(0x3200, 0x32FF)); + categoriesRangeMap.insert("IsCJKCompatibility", qMakePair(0x3300, 0x33FF)); + categoriesRangeMap.insert("IsCJKUnifiedIdeographsExtensionA", qMakePair(0x3400, 0x4DB5)); + categoriesRangeMap.insert("IsYijingHexagramSymbols", qMakePair(0x4DC0, 0x4DFF)); + categoriesRangeMap.insert("IsCJKUnifiedIdeographs", qMakePair(0x4E00, 0x9FFF)); + categoriesRangeMap.insert("IsYiSyllables", qMakePair(0xA000, 0xA48F)); + categoriesRangeMap.insert("IsYiRadicals", qMakePair(0xA490, 0xA4CF)); + categoriesRangeMap.insert("IsModifierToneLetters", qMakePair(0xA700, 0xA71F)); + categoriesRangeMap.insert("IsSylotiNagri", qMakePair(0xA800, 0xA82F)); + categoriesRangeMap.insert("IsHangulSyllables", qMakePair(0xAC00, 0xD7A3)); + categoriesRangeMap.insert("IsPrivateUse", qMakePair(0xE000, 0xF8FF)); + categoriesRangeMap.insert("IsCJKCompatibilityIdeographs", qMakePair(0xF900, 0xFAFF)); + categoriesRangeMap.insert("IsAlphabeticPresentationForms", qMakePair(0xFB00, 0xFB4F)); + categoriesRangeMap.insert("IsArabicPresentationForms-A", qMakePair(0xFB50, 0xFDFF)); + categoriesRangeMap.insert("IsVariationSelectors", qMakePair(0xFE00, 0xFE0F)); + categoriesRangeMap.insert("IsVerticalForms", qMakePair(0xFE10, 0xFE1F)); + categoriesRangeMap.insert("IsCombiningHalfMarks", qMakePair(0xFE20, 0xFE2F)); + categoriesRangeMap.insert("IsCJKCompatibilityForms", qMakePair(0xFE30, 0xFE4F)); + categoriesRangeMap.insert("IsSmallFormVariants", qMakePair(0xFE50, 0xFE6F)); + categoriesRangeMap.insert("IsArabicPresentationForms-B", qMakePair(0xFE70, 0xFEFF)); + categoriesRangeMap.insert("IsHalfwidthandFullwidthForms", qMakePair(0xFF00, 0xFFEF)); + categoriesRangeMap.insert("IsSpecials", qMakePair(0xFFF0, 0xFFFF)); + categoriesRangeMap.insert("IsLinearBSyllabary", qMakePair(0x10000, 0x1007F)); + categoriesRangeMap.insert("IsLinearBIdeograms", qMakePair(0x10080, 0x100FF)); + categoriesRangeMap.insert("IsAegeanNumbers", qMakePair(0x10100, 0x1013F)); + categoriesRangeMap.insert("IsAncientGreekNumbers", qMakePair(0x10140, 0x1018F)); + categoriesRangeMap.insert("IsOldItalic", qMakePair(0x10300, 0x1032F)); + categoriesRangeMap.insert("IsGothic", qMakePair(0x10330, 0x1034F)); + categoriesRangeMap.insert("IsUgaritic", qMakePair(0x10380, 0x1039F)); + categoriesRangeMap.insert("IsOldPersian", qMakePair(0x103A0, 0x103DF)); + categoriesRangeMap.insert("IsDeseret", qMakePair(0x10400, 0x1044F)); + categoriesRangeMap.insert("IsShavian", qMakePair(0x10450, 0x1047F)); + categoriesRangeMap.insert("IsOsmanya", qMakePair(0x10480, 0x104AF)); + categoriesRangeMap.insert("IsCypriotSyllabary", qMakePair(0x10800, 0x1083F)); + categoriesRangeMap.insert("IsKharoshthi", qMakePair(0x10A00, 0x10A5F)); + categoriesRangeMap.insert("IsByzantineMusicalSymbols", qMakePair(0x1D000, 0x1D0FF)); + categoriesRangeMap.insert("IsMusicalSymbols", qMakePair(0x1D100, 0x1D1FF)); + categoriesRangeMap.insert("IsAncientGreekMusicalNotation", qMakePair(0x1D200, 0x1D24F)); + categoriesRangeMap.insert("IsTaiXuanJingSymbols", qMakePair(0x1D300, 0x1D35F)); + categoriesRangeMap.insert("IsMathematicalAlphanumericSymbols", qMakePair(0x1D400, 0x1D7FF)); + categoriesRangeMap.insert("IsCJKUnifiedIdeographsExtensionB", qMakePair(0x20000, 0x2A6DF)); + categoriesRangeMap.insert("IsCJKCompatibilityIdeographsSupplement", qMakePair(0x2F800, 0x2FA1F)); + categoriesRangeMap.insert("IsTags", qMakePair(0xE0000, 0xE007F)); + categoriesRangeMap.insert("IsVariationSelectorsSupplement", qMakePair(0xE0100, 0xE01EF)); + categoriesRangeMap.insert("IsSupplementaryPrivateUseArea-A", qMakePair(0xF0000, 0xFFFFF)); + categoriesRangeMap.insert("IsSupplementaryPrivateUseArea-B", qMakePair(0x100000, 0x10FFFF)); +} + int QRegExpEngine::getChar() { return (yyPos == yyLen) ? EOS : yyIn[yyPos++].unicode(); @@ -2713,6 +2868,177 @@ int QRegExpEngine::getEscape() yyCharClass->addCategories(0x000f807e); yyCharClass->addSingleton(0x005f); // '_' return Tok_CharClass; + case 'I': + if (xmlSchemaExtensions) { + yyCharClass->setNegative(!yyCharClass->negative()); + // fall through + } + case 'i': + if (xmlSchemaExtensions) { + yyCharClass->addCategories(0x000f807e); + yyCharClass->addSingleton(0x003a); // ':' + yyCharClass->addSingleton(0x005f); // '_' + yyCharClass->addRange(0x0041, 0x005a); // [A-Z] + yyCharClass->addRange(0x0061, 0x007a); // [a-z] + yyCharClass->addRange(0xc0, 0xd6); + yyCharClass->addRange(0xd8, 0xf6); + yyCharClass->addRange(0xf8, 0x2ff); + yyCharClass->addRange(0x370, 0x37d); + yyCharClass->addRange(0x37f, 0x1fff); + yyCharClass->addRange(0x200c, 0x200d); + yyCharClass->addRange(0x2070, 0x218f); + yyCharClass->addRange(0x2c00, 0x2fef); + yyCharClass->addRange(0x3001, 0xd7ff); + yyCharClass->addRange(0xf900, 0xfdcf); + yyCharClass->addRange(0xfdf0, 0xfffd); + yyCharClass->addRange((ushort)0x10000, (ushort)0xeffff); + } + return Tok_CharClass; + case 'C': + if (xmlSchemaExtensions) { + yyCharClass->setNegative(!yyCharClass->negative()); + // fall through + } + case 'c': + if (xmlSchemaExtensions) { + yyCharClass->addCategories(0x000f807e); + yyCharClass->addSingleton(0x002d); // '-' + yyCharClass->addSingleton(0x002e); // '.' + yyCharClass->addSingleton(0x003a); // ':' + yyCharClass->addSingleton(0x005f); // '_' + yyCharClass->addSingleton(0xb7); + yyCharClass->addRange(0x0030, 0x0039); // [0-9] + yyCharClass->addRange(0x0041, 0x005a); // [A-Z] + yyCharClass->addRange(0x0061, 0x007a); // [a-z] + yyCharClass->addRange(0xc0, 0xd6); + yyCharClass->addRange(0xd8, 0xf6); + yyCharClass->addRange(0xf8, 0x2ff); + yyCharClass->addRange(0x370, 0x37d); + yyCharClass->addRange(0x37f, 0x1fff); + yyCharClass->addRange(0x200c, 0x200d); + yyCharClass->addRange(0x2070, 0x218f); + yyCharClass->addRange(0x2c00, 0x2fef); + yyCharClass->addRange(0x3001, 0xd7ff); + yyCharClass->addRange(0xf900, 0xfdcf); + yyCharClass->addRange(0xfdf0, 0xfffd); + yyCharClass->addRange((ushort)0x10000, (ushort)0xeffff); + yyCharClass->addRange(0x0300, 0x036f); + yyCharClass->addRange(0x203f, 0x2040); + } + return Tok_CharClass; + case 'P': + if (xmlSchemaExtensions) { + yyCharClass->setNegative(!yyCharClass->negative()); + // fall through + } + case 'p': + if (xmlSchemaExtensions) { + if (yyCh != '{') { + error(RXERR_CHARCLASS); + return Tok_CharClass; + } + + QByteArray category; + yyCh = getChar(); + while (yyCh != '}') { + if (yyCh == EOS) { + error(RXERR_END); + return Tok_CharClass; + } + category.append(yyCh); + yyCh = getChar(); + } + yyCh = getChar(); // skip closing '}' + + if (category == "M") { + yyCharClass->addCategories(0x0000000e); + } else if (category == "Mn") { + yyCharClass->addCategories(0x00000002); + } else if (category == "Mc") { + yyCharClass->addCategories(0x00000004); + } else if (category == "Me") { + yyCharClass->addCategories(0x00000008); + } else if (category == "N") { + yyCharClass->addCategories(0x00000070); + } else if (category == "Nd") { + yyCharClass->addCategories(0x00000010); + } else if (category == "Nl") { + yyCharClass->addCategories(0x00000020); + } else if (category == "No") { + yyCharClass->addCategories(0x00000040); + } else if (category == "Z") { + yyCharClass->addCategories(0x00000380); + } else if (category == "Zs") { + yyCharClass->addCategories(0x00000080); + } else if (category == "Zl") { + yyCharClass->addCategories(0x00000100); + } else if (category == "Zp") { + yyCharClass->addCategories(0x00000200); + } else if (category == "C") { + yyCharClass->addCategories(0x00006c00); + } else if (category == "Cc") { + yyCharClass->addCategories(0x00000400); + } else if (category == "Cf") { + yyCharClass->addCategories(0x00000800); + } else if (category == "Cs") { + yyCharClass->addCategories(0x00001000); + } else if (category == "Co") { + yyCharClass->addCategories(0x00002000); + } else if (category == "Cn") { + yyCharClass->addCategories(0x00004000); + } else if (category == "L") { + yyCharClass->addCategories(0x000f8000); + } else if (category == "Lu") { + yyCharClass->addCategories(0x00008000); + } else if (category == "Ll") { + yyCharClass->addCategories(0x00010000); + } else if (category == "Lt") { + yyCharClass->addCategories(0x00020000); + } else if (category == "Lm") { + yyCharClass->addCategories(0x00040000); + } else if (category == "Lo") { + yyCharClass->addCategories(0x00080000); + } else if (category == "P") { + yyCharClass->addCategories(0x4f580780); + } else if (category == "Pc") { + yyCharClass->addCategories(0x00100000); + } else if (category == "Pd") { + yyCharClass->addCategories(0x00200000); + } else if (category == "Ps") { + yyCharClass->addCategories(0x00400000); + } else if (category == "Pe") { + yyCharClass->addCategories(0x00800000); + } else if (category == "Pi") { + yyCharClass->addCategories(0x01000000); + } else if (category == "Pf") { + yyCharClass->addCategories(0x02000000); + } else if (category == "Po") { + yyCharClass->addCategories(0x04000000); + } else if (category == "S") { + yyCharClass->addCategories(0x78000000); + } else if (category == "Sm") { + yyCharClass->addCategories(0x08000000); + } else if (category == "Sc") { + yyCharClass->addCategories(0x10000000); + } else if (category == "Sk") { + yyCharClass->addCategories(0x20000000); + } else if (category == "So") { + yyCharClass->addCategories(0x40000000); + } else if (category.startsWith("Is")) { + if (categoriesRangeMap.isEmpty()) + setupCategoriesRangeMap(); + + if (categoriesRangeMap.contains(category)) { + const QPair range = categoriesRangeMap.value(category); + yyCharClass->addRange(range.first, range.second); + } else { + error(RXERR_CATEGORY); + } + } else { + error(RXERR_CATEGORY); + } + } + return Tok_CharClass; #endif #ifndef QT_NO_REGEXP_ESCAPE case 'x': @@ -2934,7 +3260,7 @@ int QRegExpEngine::getToken() yyMaxRep = getRep(InftyRep); } if (yyMaxRep < yyMinRep) - qSwap(yyMinRep, yyMaxRep); + error(RXERR_INTERVAL); if (yyCh != '}') error(RXERR_REPETITION); yyCh = getChar(); diff --git a/src/corelib/tools/qregexp.h b/src/corelib/tools/qregexp.h index b387e23..f2e3d3b 100644 --- a/src/corelib/tools/qregexp.h +++ b/src/corelib/tools/qregexp.h @@ -61,7 +61,7 @@ class QStringList; class Q_CORE_EXPORT QRegExp { public: - enum PatternSyntax { RegExp, Wildcard, FixedString, RegExp2 }; + enum PatternSyntax { RegExp, Wildcard, FixedString, RegExp2, W3CXmlSchema11 }; enum CaretMode { CaretAtZero, CaretAtOffset, CaretWontMatch }; QRegExp(); -- cgit v0.12 From 135a028d9dc9a28a0a072665a7dc43b7e9e187be Mon Sep 17 00:00:00 2001 From: Tobias Koenig Date: Sat, 16 May 2009 12:19:10 +0200 Subject: Add W3C XML Schema validation support This was done by Tobias Koenig, as part of an internship at Trolltech/Qt Software, started at Wed Oct 1 18:32:43 2008 +0200, and the last commit being part of this commit dating Tue Feb 24 11:03:36 2009 +0100. This is work consisting of about 650 commits squashed into one, where the first commit was 61b280386c1905a15690fdd917dcbc8eb09b6283, in the repository before Qt's history cut. --- examples/tools/regexp/regexpdialog.cpp | 1 + examples/xmlpatterns/schema/main.cpp | 24 + examples/xmlpatterns/schema/mainwindow.cpp | 175 + examples/xmlpatterns/schema/mainwindow.h | 38 + examples/xmlpatterns/schema/schema.pro | 11 + examples/xmlpatterns/schema/schema.qrc | 13 + examples/xmlpatterns/schema/schema.ui | 71 + examples/xmlpatterns/xmlpatterns.pro | 3 +- src/xmlpatterns/Doxyfile | 2 +- src/xmlpatterns/acceltree/qacceltree.cpp | 43 + src/xmlpatterns/acceltree/qacceltree_p.h | 17 +- src/xmlpatterns/acceltree/qacceltreebuilder.cpp | 31 +- src/xmlpatterns/acceltree/qacceltreebuilder_p.h | 19 +- .../acceltree/qacceltreeresourceloader.cpp | 60 +- .../acceltree/qacceltreeresourceloader_p.h | 27 +- src/xmlpatterns/api/api.pri | 11 + src/xmlpatterns/api/qabstractxmlnodemodel.cpp | 16 + src/xmlpatterns/api/qabstractxmlnodemodel.h | 5 + src/xmlpatterns/api/qabstractxmlnodemodel_p.h | 10 + src/xmlpatterns/api/qabstractxmlpullprovider.cpp | 147 + src/xmlpatterns/api/qabstractxmlpullprovider_p.h | 83 + src/xmlpatterns/api/qpullbridge.cpp | 202 + src/xmlpatterns/api/qpullbridge_p.h | 73 + src/xmlpatterns/api/qresourcedelegator.cpp | 8 - src/xmlpatterns/api/qxmlnamepool.cpp | 4 + src/xmlpatterns/api/qxmlnamepool.h | 7 + src/xmlpatterns/api/qxmlquery.cpp | 12 + src/xmlpatterns/api/qxmlquery.h | 11 +- src/xmlpatterns/api/qxmlquery_p.h | 24 +- src/xmlpatterns/api/qxmlschema.cpp | 229 + src/xmlpatterns/api/qxmlschema.h | 66 + src/xmlpatterns/api/qxmlschema_p.cpp | 169 + src/xmlpatterns/api/qxmlschema_p.h | 79 + src/xmlpatterns/api/qxmlschemavalidator.cpp | 264 + src/xmlpatterns/api/qxmlschemavalidator.h | 64 + src/xmlpatterns/api/qxmlschemavalidator_p.h | 98 + src/xmlpatterns/common.pri | 1 + src/xmlpatterns/data/data.pri | 20 +- src/xmlpatterns/data/qcomparisonfactory.cpp | 124 + src/xmlpatterns/data/qcomparisonfactory_p.h | 91 + src/xmlpatterns/data/qitem_p.h | 5 + src/xmlpatterns/data/qvaluefactory.cpp | 76 + src/xmlpatterns/data/qvaluefactory_p.h | 68 + .../environment/createReportContext.xsl | 5 + src/xmlpatterns/environment/qreportcontext.cpp | 1 + src/xmlpatterns/environment/qreportcontext_p.h | 4 + src/xmlpatterns/expr/qcastingplatform.cpp | 22 +- src/xmlpatterns/expr/qcastingplatform_p.h | 23 +- src/xmlpatterns/expr/qexpressionfactory.cpp | 27 +- src/xmlpatterns/functions/qpatternplatform.cpp | 21 +- src/xmlpatterns/functions/qpatternplatform_p.h | 18 +- src/xmlpatterns/parser/qquerytransformparser.cpp | 944 +-- src/xmlpatterns/parser/qquerytransformparser_p.h | 40 + src/xmlpatterns/parser/querytransformparser.ypp | 174 +- src/xmlpatterns/schema/.gitignore | 1 + src/xmlpatterns/schema/builtinschemas.qrc | 5 + src/xmlpatterns/schema/doc/All_diagram.dot | 13 + src/xmlpatterns/schema/doc/Alternative_diagram.dot | 11 + src/xmlpatterns/schema/doc/Annotation_diagram.dot | 9 + .../schema/doc/AnyAttribute_diagram.dot | 6 + src/xmlpatterns/schema/doc/Any_diagram.dot | 6 + src/xmlpatterns/schema/doc/Assert_diagram.dot | 6 + src/xmlpatterns/schema/doc/Choice_diagram.dot | 22 + .../schema/doc/ComplexContentExtension_diagram.dot | 47 + .../doc/ComplexContentRestriction_diagram.dot | 47 + .../schema/doc/ComplexContent_diagram.dot | 11 + .../schema/doc/DefaultOpenContent_diagram.dot | 9 + .../schema/doc/EnumerationFacet_diagram.dot | 6 + src/xmlpatterns/schema/doc/Field_diagram.dot | 6 + .../schema/doc/FractionDigitsFacet_diagram.dot | 6 + .../schema/doc/GlobalAttribute_diagram.dot | 9 + .../schema/doc/GlobalComplexType_diagram.dot | 52 + .../schema/doc/GlobalElement_diagram.dot | 32 + .../schema/doc/GlobalSimpleType_diagram.dot | 13 + src/xmlpatterns/schema/doc/Import_diagram.dot | 6 + src/xmlpatterns/schema/doc/Include_diagram.dot | 6 + src/xmlpatterns/schema/doc/KeyRef_diagram.dot | 12 + src/xmlpatterns/schema/doc/Key_diagram.dot | 12 + src/xmlpatterns/schema/doc/LengthFacet_diagram.dot | 6 + src/xmlpatterns/schema/doc/List_diagram.dot | 9 + src/xmlpatterns/schema/doc/LocalAll_diagram.dot | 13 + .../schema/doc/LocalAttribute_diagram.dot | 9 + src/xmlpatterns/schema/doc/LocalChoice_diagram.dot | 22 + .../schema/doc/LocalComplexType_diagram.dot | 52 + .../schema/doc/LocalElement_diagram.dot | 32 + .../schema/doc/LocalSequence_diagram.dot | 22 + .../schema/doc/LocalSimpleType_diagram.dot | 13 + .../schema/doc/MaxExclusiveFacet_diagram.dot | 6 + .../schema/doc/MaxInclusiveFacet_diagram.dot | 6 + .../schema/doc/MaxLengthFacet_diagram.dot | 6 + .../schema/doc/MinExclusiveFacet_diagram.dot | 6 + .../schema/doc/MinInclusiveFacet_diagram.dot | 6 + .../schema/doc/MinLengthFacet_diagram.dot | 6 + .../schema/doc/NamedAttributeGroup_diagram.dot | 17 + src/xmlpatterns/schema/doc/NamedGroup_diagram.dot | 13 + src/xmlpatterns/schema/doc/Notation_diagram.dot | 6 + src/xmlpatterns/schema/doc/Override_diagram.dot | 21 + .../schema/doc/PatternFacet_diagram.dot | 6 + src/xmlpatterns/schema/doc/Redefine_diagram.dot | 15 + .../schema/doc/ReferredAttributeGroup_diagram.dot | 6 + .../schema/doc/ReferredGroup_diagram.dot | 13 + src/xmlpatterns/schema/doc/Schema_diagram.dot | 66 + src/xmlpatterns/schema/doc/Selector_diagram.dot | 6 + src/xmlpatterns/schema/doc/Sequence_diagram.dot | 22 + .../schema/doc/SimpleContentExtension_diagram.dot | 23 + .../doc/SimpleContentRestriction_diagram.dot | 87 + .../schema/doc/SimpleContent_diagram.dot | 11 + .../schema/doc/SimpleRestriction_diagram.dot | 62 + .../schema/doc/TotalDigitsFacet_diagram.dot | 6 + src/xmlpatterns/schema/doc/Union_diagram.dot | 10 + src/xmlpatterns/schema/doc/Unique_diagram.dot | 12 + .../schema/doc/WhiteSpaceFacet_diagram.dot | 6 + src/xmlpatterns/schema/doc/legend.dot | 7 + src/xmlpatterns/schema/qnamespacesupport.cpp | 132 + src/xmlpatterns/schema/qnamespacesupport_p.h | 143 + src/xmlpatterns/schema/qxsdalternative.cpp | 38 + src/xmlpatterns/schema/qxsdalternative_p.h | 84 + src/xmlpatterns/schema/qxsdannotated.cpp | 33 + src/xmlpatterns/schema/qxsdannotated_p.h | 66 + src/xmlpatterns/schema/qxsdannotation.cpp | 48 + src/xmlpatterns/schema/qxsdannotation_p.h | 97 + .../schema/qxsdapplicationinformation.cpp | 38 + .../schema/qxsdapplicationinformation_p.h | 85 + src/xmlpatterns/schema/qxsdassertion.cpp | 28 + src/xmlpatterns/schema/qxsdassertion_p.h | 71 + src/xmlpatterns/schema/qxsdattribute.cpp | 100 + src/xmlpatterns/schema/qxsdattribute_p.h | 216 + src/xmlpatterns/schema/qxsdattributegroup.cpp | 43 + src/xmlpatterns/schema/qxsdattributegroup_p.h | 92 + src/xmlpatterns/schema/qxsdattributereference.cpp | 58 + src/xmlpatterns/schema/qxsdattributereference_p.h | 117 + src/xmlpatterns/schema/qxsdattributeterm.cpp | 28 + src/xmlpatterns/schema/qxsdattributeterm_p.h | 66 + src/xmlpatterns/schema/qxsdattributeuse.cpp | 106 + src/xmlpatterns/schema/qxsdattributeuse_p.h | 194 + src/xmlpatterns/schema/qxsdcomplextype.cpp | 201 + src/xmlpatterns/schema/qxsdcomplextype_p.h | 374 ++ src/xmlpatterns/schema/qxsddocumentation.cpp | 56 + src/xmlpatterns/schema/qxsddocumentation_p.h | 107 + src/xmlpatterns/schema/qxsdelement.cpp | 214 + src/xmlpatterns/schema/qxsdelement_p.h | 373 ++ src/xmlpatterns/schema/qxsdfacet.cpp | 94 + src/xmlpatterns/schema/qxsdfacet_p.h | 183 + src/xmlpatterns/schema/qxsdidcache.cpp | 36 + src/xmlpatterns/schema/qxsdidcache_p.h | 69 + src/xmlpatterns/schema/qxsdidchelper.cpp | 107 + src/xmlpatterns/schema/qxsdidchelper_p.h | 156 + src/xmlpatterns/schema/qxsdidentityconstraint.cpp | 63 + src/xmlpatterns/schema/qxsdidentityconstraint_p.h | 143 + src/xmlpatterns/schema/qxsdinstancereader.cpp | 166 + src/xmlpatterns/schema/qxsdinstancereader_p.h | 159 + src/xmlpatterns/schema/qxsdmodelgroup.cpp | 48 + src/xmlpatterns/schema/qxsdmodelgroup_p.h | 109 + src/xmlpatterns/schema/qxsdnotation.cpp | 38 + src/xmlpatterns/schema/qxsdnotation_p.h | 89 + src/xmlpatterns/schema/qxsdparticle.cpp | 65 + src/xmlpatterns/schema/qxsdparticle_p.h | 124 + src/xmlpatterns/schema/qxsdparticlechecker.cpp | 510 ++ src/xmlpatterns/schema/qxsdparticlechecker_p.h | 69 + src/xmlpatterns/schema/qxsdreference.cpp | 53 + src/xmlpatterns/schema/qxsdreference_p.h | 115 + src/xmlpatterns/schema/qxsdschema.cpp | 242 + src/xmlpatterns/schema/qxsdschema_p.h | 271 + src/xmlpatterns/schema/qxsdschemachecker.cpp | 2031 +++++++ .../schema/qxsdschemachecker_helper.cpp | 276 + src/xmlpatterns/schema/qxsdschemachecker_p.h | 254 + src/xmlpatterns/schema/qxsdschemachecker_setup.cpp | 287 + src/xmlpatterns/schema/qxsdschemacontext.cpp | 498 ++ src/xmlpatterns/schema/qxsdschemacontext_p.h | 157 + src/xmlpatterns/schema/qxsdschemadebugger.cpp | 196 + src/xmlpatterns/schema/qxsdschemadebugger_p.h | 97 + src/xmlpatterns/schema/qxsdschemahelper.cpp | 791 +++ src/xmlpatterns/schema/qxsdschemahelper_p.h | 156 + src/xmlpatterns/schema/qxsdschemamerger.cpp | 127 + src/xmlpatterns/schema/qxsdschemamerger_p.h | 69 + src/xmlpatterns/schema/qxsdschemaparser.cpp | 6012 ++++++++++++++++++++ src/xmlpatterns/schema/qxsdschemaparser_p.h | 691 +++ src/xmlpatterns/schema/qxsdschemaparser_setup.cpp | 1070 ++++ src/xmlpatterns/schema/qxsdschemaparsercontext.cpp | 573 ++ src/xmlpatterns/schema/qxsdschemaparsercontext_p.h | 201 + src/xmlpatterns/schema/qxsdschemaresolver.cpp | 1706 ++++++ src/xmlpatterns/schema/qxsdschemaresolver_p.h | 548 ++ src/xmlpatterns/schema/qxsdschematoken.cpp | 2951 ++++++++++ src/xmlpatterns/schema/qxsdschematoken_p.h | 168 + src/xmlpatterns/schema/qxsdschematypesfactory.cpp | 96 + src/xmlpatterns/schema/qxsdschematypesfactory_p.h | 79 + src/xmlpatterns/schema/qxsdsimpletype.cpp | 118 + src/xmlpatterns/schema/qxsdsimpletype_p.h | 189 + src/xmlpatterns/schema/qxsdstatemachine.cpp | 433 ++ src/xmlpatterns/schema/qxsdstatemachine_p.h | 209 + src/xmlpatterns/schema/qxsdstatemachinebuilder.cpp | 230 + src/xmlpatterns/schema/qxsdstatemachinebuilder_p.h | 111 + src/xmlpatterns/schema/qxsdterm.cpp | 38 + src/xmlpatterns/schema/qxsdterm_p.h | 84 + src/xmlpatterns/schema/qxsdtypechecker.cpp | 1308 +++++ src/xmlpatterns/schema/qxsdtypechecker_p.h | 159 + src/xmlpatterns/schema/qxsduserschematype.cpp | 45 + src/xmlpatterns/schema/qxsduserschematype_p.h | 94 + .../schema/qxsdvalidatedxmlnodemodel.cpp | 185 + .../schema/qxsdvalidatedxmlnodemodel_p.h | 149 + .../schema/qxsdvalidatinginstancereader.cpp | 1245 ++++ .../schema/qxsdvalidatinginstancereader_p.h | 266 + src/xmlpatterns/schema/qxsdwildcard.cpp | 85 + src/xmlpatterns/schema/qxsdwildcard_p.h | 169 + src/xmlpatterns/schema/qxsdxpathexpression.cpp | 58 + src/xmlpatterns/schema/qxsdxpathexpression_p.h | 113 + src/xmlpatterns/schema/schema.pri | 93 + src/xmlpatterns/schema/schemas/xml.xsd | 145 + src/xmlpatterns/schema/tokens.xml | 125 + src/xmlpatterns/type/qanysimpletype.cpp | 10 + src/xmlpatterns/type/qanysimpletype_p.h | 12 + src/xmlpatterns/type/qanytype.cpp | 12 +- src/xmlpatterns/type/qanytype_p.h | 10 + src/xmlpatterns/type/qnamedschemacomponent.cpp | 41 + src/xmlpatterns/type/qnamedschemacomponent_p.h | 97 + src/xmlpatterns/type/qprimitives_p.h | 13 + src/xmlpatterns/type/qschematype.cpp | 5 + src/xmlpatterns/type/qschematype_p.h | 30 +- src/xmlpatterns/type/type.pri | 2 + src/xmlpatterns/utils/qpatternistlocale_p.h | 10 + src/xmlpatterns/xmlpatterns.pro | 2 + tests/auto/auto.pro | 5 + .../tst_qabstractxmlnodemodel.cpp | 8 + tests/auto/qxmlquery/tst_qxmlquery.cpp | 158 + tests/auto/qxmlschema/.gitignore | 1 + tests/auto/qxmlschema/qxmlschema.pro | 4 + tests/auto/qxmlschema/tst_qxmlschema.cpp | 231 + tests/auto/qxmlschemavalidator/.gitignore | 1 + .../qxmlschemavalidator/qxmlschemavalidator.pro | 4 + .../tst_qxmlschemavalidator.cpp | 308 + tests/auto/runQtXmlPatternsTests.sh | 2 + tests/auto/xmlpatterns.pri | 14 + .../test/tst_xmlpatternsdiagnosticsts.cpp | 2 +- tests/auto/xmlpatternsschema/.gitignore | 1 + .../xmlpatternsschema/tst_xmlpatternsschema.cpp | 988 ++++ tests/auto/xmlpatternsschema/xmlpatternsschema.pro | 6 + tests/auto/xmlpatternsschemats/.gitignore | 4 + tests/auto/xmlpatternsschemats/Baseline.xml | 2 + .../auto/xmlpatternsschemats/TESTSUITE/.gitignore | 3 + .../xmlpatternsschemats/TESTSUITE/unifyCatalog.xsl | 21 + .../xmlpatternsschemats/TESTSUITE/updateSuite.sh | 20 + .../tst_xmlpatternsschemats.cpp | 44 + .../xmlpatternsschemats/xmlpatternsschemats.pro | 23 + tests/auto/xmlpatternsvalidator/files/instance.xml | 3 + .../xmlpatternsvalidator/files/invalid_schema.xsd | 12 + .../files/other_valid_schema.xsd | 12 + .../files/sa_invalid_instance.xml | 3 + .../files/sa_valid_instance.xml | 3 + .../xmlpatternsvalidator/files/valid_schema.xsd | 12 + .../tst_xmlpatternsvalidator.cpp | 174 + .../xmlpatternsvalidator/xmlpatternsvalidator.pro | 5 + tests/auto/xmlpatternsview/view/MainWindow.cpp | 32 +- tests/auto/xmlpatternsview/view/MainWindow.h | 6 +- tests/auto/xmlpatternsview/view/ui_MainWindow.ui | 9 + tests/auto/xmlpatternsxqts/lib/TestBaseLine.cpp | 7 + tests/auto/xmlpatternsxqts/lib/TestBaseLine.h | 9 +- tests/auto/xmlpatternsxqts/lib/TestGroup.cpp | 6 +- tests/auto/xmlpatternsxqts/lib/TestSuite.cpp | 26 +- tests/auto/xmlpatternsxqts/lib/TestSuite.h | 14 +- tests/auto/xmlpatternsxqts/lib/TreeModel.cpp | 9 +- tests/auto/xmlpatternsxqts/lib/XSDTSTestCase.cpp | 346 ++ tests/auto/xmlpatternsxqts/lib/XSDTSTestCase.h | 130 + .../xmlpatternsxqts/lib/XSDTestSuiteHandler.cpp | 881 +++ .../auto/xmlpatternsxqts/lib/XSDTestSuiteHandler.h | 90 + tests/auto/xmlpatternsxqts/lib/lib.pro | 4 + tests/auto/xmlpatternsxqts/test/tst_suitetest.cpp | 15 +- tests/auto/xmlpatternsxqts/test/tst_suitetest.h | 14 +- .../xmlpatternsxqts/test/tst_xmlpatternsxqts.cpp | 2 +- .../auto/xmlpatternsxslts/tst_xmlpatternsxslts.cpp | 2 +- tools/tools.pro | 2 +- tools/xmlpatternsvalidator/main.cpp | 96 + tools/xmlpatternsvalidator/main.h | 46 + .../xmlpatternsvalidator/xmlpatternsvalidator.pro | 19 + 273 files changed, 39053 insertions(+), 595 deletions(-) create mode 100644 examples/xmlpatterns/schema/main.cpp create mode 100644 examples/xmlpatterns/schema/mainwindow.cpp create mode 100644 examples/xmlpatterns/schema/mainwindow.h create mode 100644 examples/xmlpatterns/schema/schema.pro create mode 100644 examples/xmlpatterns/schema/schema.qrc create mode 100644 examples/xmlpatterns/schema/schema.ui create mode 100644 src/xmlpatterns/api/qabstractxmlpullprovider.cpp create mode 100644 src/xmlpatterns/api/qabstractxmlpullprovider_p.h create mode 100644 src/xmlpatterns/api/qpullbridge.cpp create mode 100644 src/xmlpatterns/api/qpullbridge_p.h create mode 100644 src/xmlpatterns/api/qxmlschema.cpp create mode 100644 src/xmlpatterns/api/qxmlschema.h create mode 100644 src/xmlpatterns/api/qxmlschema_p.cpp create mode 100644 src/xmlpatterns/api/qxmlschema_p.h create mode 100644 src/xmlpatterns/api/qxmlschemavalidator.cpp create mode 100644 src/xmlpatterns/api/qxmlschemavalidator.h create mode 100644 src/xmlpatterns/api/qxmlschemavalidator_p.h create mode 100644 src/xmlpatterns/data/qcomparisonfactory.cpp create mode 100644 src/xmlpatterns/data/qcomparisonfactory_p.h create mode 100644 src/xmlpatterns/data/qvaluefactory.cpp create mode 100644 src/xmlpatterns/data/qvaluefactory_p.h create mode 100644 src/xmlpatterns/schema/.gitignore create mode 100644 src/xmlpatterns/schema/builtinschemas.qrc create mode 100644 src/xmlpatterns/schema/doc/All_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/Alternative_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/Annotation_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/AnyAttribute_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/Any_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/Assert_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/Choice_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/ComplexContentExtension_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/ComplexContentRestriction_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/ComplexContent_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/DefaultOpenContent_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/EnumerationFacet_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/Field_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/FractionDigitsFacet_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/GlobalAttribute_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/GlobalComplexType_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/GlobalElement_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/GlobalSimpleType_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/Import_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/Include_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/KeyRef_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/Key_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/LengthFacet_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/List_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/LocalAll_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/LocalAttribute_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/LocalChoice_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/LocalComplexType_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/LocalElement_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/LocalSequence_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/LocalSimpleType_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/MaxExclusiveFacet_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/MaxInclusiveFacet_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/MaxLengthFacet_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/MinExclusiveFacet_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/MinInclusiveFacet_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/MinLengthFacet_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/NamedAttributeGroup_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/NamedGroup_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/Notation_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/Override_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/PatternFacet_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/Redefine_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/ReferredAttributeGroup_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/ReferredGroup_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/Schema_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/Selector_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/Sequence_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/SimpleContentExtension_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/SimpleContentRestriction_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/SimpleContent_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/SimpleRestriction_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/TotalDigitsFacet_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/Union_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/Unique_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/WhiteSpaceFacet_diagram.dot create mode 100644 src/xmlpatterns/schema/doc/legend.dot create mode 100644 src/xmlpatterns/schema/qnamespacesupport.cpp create mode 100644 src/xmlpatterns/schema/qnamespacesupport_p.h create mode 100644 src/xmlpatterns/schema/qxsdalternative.cpp create mode 100644 src/xmlpatterns/schema/qxsdalternative_p.h create mode 100644 src/xmlpatterns/schema/qxsdannotated.cpp create mode 100644 src/xmlpatterns/schema/qxsdannotated_p.h create mode 100644 src/xmlpatterns/schema/qxsdannotation.cpp create mode 100644 src/xmlpatterns/schema/qxsdannotation_p.h create mode 100644 src/xmlpatterns/schema/qxsdapplicationinformation.cpp create mode 100644 src/xmlpatterns/schema/qxsdapplicationinformation_p.h create mode 100644 src/xmlpatterns/schema/qxsdassertion.cpp create mode 100644 src/xmlpatterns/schema/qxsdassertion_p.h create mode 100644 src/xmlpatterns/schema/qxsdattribute.cpp create mode 100644 src/xmlpatterns/schema/qxsdattribute_p.h create mode 100644 src/xmlpatterns/schema/qxsdattributegroup.cpp create mode 100644 src/xmlpatterns/schema/qxsdattributegroup_p.h create mode 100644 src/xmlpatterns/schema/qxsdattributereference.cpp create mode 100644 src/xmlpatterns/schema/qxsdattributereference_p.h create mode 100644 src/xmlpatterns/schema/qxsdattributeterm.cpp create mode 100644 src/xmlpatterns/schema/qxsdattributeterm_p.h create mode 100644 src/xmlpatterns/schema/qxsdattributeuse.cpp create mode 100644 src/xmlpatterns/schema/qxsdattributeuse_p.h create mode 100644 src/xmlpatterns/schema/qxsdcomplextype.cpp create mode 100644 src/xmlpatterns/schema/qxsdcomplextype_p.h create mode 100644 src/xmlpatterns/schema/qxsddocumentation.cpp create mode 100644 src/xmlpatterns/schema/qxsddocumentation_p.h create mode 100644 src/xmlpatterns/schema/qxsdelement.cpp create mode 100644 src/xmlpatterns/schema/qxsdelement_p.h create mode 100644 src/xmlpatterns/schema/qxsdfacet.cpp create mode 100644 src/xmlpatterns/schema/qxsdfacet_p.h create mode 100644 src/xmlpatterns/schema/qxsdidcache.cpp create mode 100644 src/xmlpatterns/schema/qxsdidcache_p.h create mode 100644 src/xmlpatterns/schema/qxsdidchelper.cpp create mode 100644 src/xmlpatterns/schema/qxsdidchelper_p.h create mode 100644 src/xmlpatterns/schema/qxsdidentityconstraint.cpp create mode 100644 src/xmlpatterns/schema/qxsdidentityconstraint_p.h create mode 100644 src/xmlpatterns/schema/qxsdinstancereader.cpp create mode 100644 src/xmlpatterns/schema/qxsdinstancereader_p.h create mode 100644 src/xmlpatterns/schema/qxsdmodelgroup.cpp create mode 100644 src/xmlpatterns/schema/qxsdmodelgroup_p.h create mode 100644 src/xmlpatterns/schema/qxsdnotation.cpp create mode 100644 src/xmlpatterns/schema/qxsdnotation_p.h create mode 100644 src/xmlpatterns/schema/qxsdparticle.cpp create mode 100644 src/xmlpatterns/schema/qxsdparticle_p.h create mode 100644 src/xmlpatterns/schema/qxsdparticlechecker.cpp create mode 100644 src/xmlpatterns/schema/qxsdparticlechecker_p.h create mode 100644 src/xmlpatterns/schema/qxsdreference.cpp create mode 100644 src/xmlpatterns/schema/qxsdreference_p.h create mode 100644 src/xmlpatterns/schema/qxsdschema.cpp create mode 100644 src/xmlpatterns/schema/qxsdschema_p.h create mode 100644 src/xmlpatterns/schema/qxsdschemachecker.cpp create mode 100644 src/xmlpatterns/schema/qxsdschemachecker_helper.cpp create mode 100644 src/xmlpatterns/schema/qxsdschemachecker_p.h create mode 100644 src/xmlpatterns/schema/qxsdschemachecker_setup.cpp create mode 100644 src/xmlpatterns/schema/qxsdschemacontext.cpp create mode 100644 src/xmlpatterns/schema/qxsdschemacontext_p.h create mode 100644 src/xmlpatterns/schema/qxsdschemadebugger.cpp create mode 100644 src/xmlpatterns/schema/qxsdschemadebugger_p.h create mode 100644 src/xmlpatterns/schema/qxsdschemahelper.cpp create mode 100644 src/xmlpatterns/schema/qxsdschemahelper_p.h create mode 100644 src/xmlpatterns/schema/qxsdschemamerger.cpp create mode 100644 src/xmlpatterns/schema/qxsdschemamerger_p.h create mode 100644 src/xmlpatterns/schema/qxsdschemaparser.cpp create mode 100644 src/xmlpatterns/schema/qxsdschemaparser_p.h create mode 100644 src/xmlpatterns/schema/qxsdschemaparser_setup.cpp create mode 100644 src/xmlpatterns/schema/qxsdschemaparsercontext.cpp create mode 100644 src/xmlpatterns/schema/qxsdschemaparsercontext_p.h create mode 100644 src/xmlpatterns/schema/qxsdschemaresolver.cpp create mode 100644 src/xmlpatterns/schema/qxsdschemaresolver_p.h create mode 100644 src/xmlpatterns/schema/qxsdschematoken.cpp create mode 100644 src/xmlpatterns/schema/qxsdschematoken_p.h create mode 100644 src/xmlpatterns/schema/qxsdschematypesfactory.cpp create mode 100644 src/xmlpatterns/schema/qxsdschematypesfactory_p.h create mode 100644 src/xmlpatterns/schema/qxsdsimpletype.cpp create mode 100644 src/xmlpatterns/schema/qxsdsimpletype_p.h create mode 100644 src/xmlpatterns/schema/qxsdstatemachine.cpp create mode 100644 src/xmlpatterns/schema/qxsdstatemachine_p.h create mode 100644 src/xmlpatterns/schema/qxsdstatemachinebuilder.cpp create mode 100644 src/xmlpatterns/schema/qxsdstatemachinebuilder_p.h create mode 100644 src/xmlpatterns/schema/qxsdterm.cpp create mode 100644 src/xmlpatterns/schema/qxsdterm_p.h create mode 100644 src/xmlpatterns/schema/qxsdtypechecker.cpp create mode 100644 src/xmlpatterns/schema/qxsdtypechecker_p.h create mode 100644 src/xmlpatterns/schema/qxsduserschematype.cpp create mode 100644 src/xmlpatterns/schema/qxsduserschematype_p.h create mode 100644 src/xmlpatterns/schema/qxsdvalidatedxmlnodemodel.cpp create mode 100644 src/xmlpatterns/schema/qxsdvalidatedxmlnodemodel_p.h create mode 100644 src/xmlpatterns/schema/qxsdvalidatinginstancereader.cpp create mode 100644 src/xmlpatterns/schema/qxsdvalidatinginstancereader_p.h create mode 100644 src/xmlpatterns/schema/qxsdwildcard.cpp create mode 100644 src/xmlpatterns/schema/qxsdwildcard_p.h create mode 100644 src/xmlpatterns/schema/qxsdxpathexpression.cpp create mode 100644 src/xmlpatterns/schema/qxsdxpathexpression_p.h create mode 100644 src/xmlpatterns/schema/schema.pri create mode 100644 src/xmlpatterns/schema/schemas/xml.xsd create mode 100644 src/xmlpatterns/schema/tokens.xml create mode 100644 src/xmlpatterns/type/qnamedschemacomponent.cpp create mode 100644 src/xmlpatterns/type/qnamedschemacomponent_p.h create mode 100644 tests/auto/qxmlschema/.gitignore create mode 100644 tests/auto/qxmlschema/qxmlschema.pro create mode 100644 tests/auto/qxmlschema/tst_qxmlschema.cpp create mode 100644 tests/auto/qxmlschemavalidator/.gitignore create mode 100644 tests/auto/qxmlschemavalidator/qxmlschemavalidator.pro create mode 100644 tests/auto/qxmlschemavalidator/tst_qxmlschemavalidator.cpp create mode 100644 tests/auto/xmlpatternsschema/.gitignore create mode 100644 tests/auto/xmlpatternsschema/tst_xmlpatternsschema.cpp create mode 100644 tests/auto/xmlpatternsschema/xmlpatternsschema.pro create mode 100644 tests/auto/xmlpatternsschemats/.gitignore create mode 100644 tests/auto/xmlpatternsschemats/Baseline.xml create mode 100644 tests/auto/xmlpatternsschemats/TESTSUITE/.gitignore create mode 100644 tests/auto/xmlpatternsschemats/TESTSUITE/unifyCatalog.xsl create mode 100755 tests/auto/xmlpatternsschemats/TESTSUITE/updateSuite.sh create mode 100644 tests/auto/xmlpatternsschemats/tst_xmlpatternsschemats.cpp create mode 100644 tests/auto/xmlpatternsschemats/xmlpatternsschemats.pro create mode 100644 tests/auto/xmlpatternsvalidator/files/instance.xml create mode 100644 tests/auto/xmlpatternsvalidator/files/invalid_schema.xsd create mode 100644 tests/auto/xmlpatternsvalidator/files/other_valid_schema.xsd create mode 100644 tests/auto/xmlpatternsvalidator/files/sa_invalid_instance.xml create mode 100644 tests/auto/xmlpatternsvalidator/files/sa_valid_instance.xml create mode 100644 tests/auto/xmlpatternsvalidator/files/valid_schema.xsd create mode 100644 tests/auto/xmlpatternsvalidator/tst_xmlpatternsvalidator.cpp create mode 100644 tests/auto/xmlpatternsvalidator/xmlpatternsvalidator.pro create mode 100644 tests/auto/xmlpatternsxqts/lib/XSDTSTestCase.cpp create mode 100644 tests/auto/xmlpatternsxqts/lib/XSDTSTestCase.h create mode 100644 tests/auto/xmlpatternsxqts/lib/XSDTestSuiteHandler.cpp create mode 100644 tests/auto/xmlpatternsxqts/lib/XSDTestSuiteHandler.h create mode 100644 tools/xmlpatternsvalidator/main.cpp create mode 100644 tools/xmlpatternsvalidator/main.h create mode 100644 tools/xmlpatternsvalidator/xmlpatternsvalidator.pro diff --git a/examples/tools/regexp/regexpdialog.cpp b/examples/tools/regexp/regexpdialog.cpp index 8fe7383..52805c1 100644 --- a/examples/tools/regexp/regexpdialog.cpp +++ b/examples/tools/regexp/regexpdialog.cpp @@ -69,6 +69,7 @@ RegExpDialog::RegExpDialog(QWidget *parent) syntaxComboBox->addItem(tr("Regular expression v2"), QRegExp::RegExp2); syntaxComboBox->addItem(tr("Wildcard"), QRegExp::Wildcard); syntaxComboBox->addItem(tr("Fixed string"), QRegExp::FixedString); + syntaxComboBox->addItem(tr("W3C Xml Schema 1.1"), QRegExp::W3CXmlSchema11); syntaxLabel = new QLabel(tr("&Pattern Syntax:")); syntaxLabel->setBuddy(syntaxComboBox); diff --git a/examples/xmlpatterns/schema/main.cpp b/examples/xmlpatterns/schema/main.cpp new file mode 100644 index 0000000..9537a87 --- /dev/null +++ b/examples/xmlpatterns/schema/main.cpp @@ -0,0 +1,24 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include +#include "mainwindow.h" + +//! [0] +int main(int argc, char* argv[]) +{ + Q_INIT_RESOURCE(schema); + QApplication app(argc, argv); + MainWindow* const window = new MainWindow; + window->show(); + return app.exec(); +} +//! [0] diff --git a/examples/xmlpatterns/schema/mainwindow.cpp b/examples/xmlpatterns/schema/mainwindow.cpp new file mode 100644 index 0000000..807a65b --- /dev/null +++ b/examples/xmlpatterns/schema/mainwindow.cpp @@ -0,0 +1,175 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include "mainwindow.h" +#include "xmlsyntaxhighlighter.h" + +class MessageHandler : public QAbstractMessageHandler +{ + public: + MessageHandler() + : QAbstractMessageHandler(0) + { + } + + QString statusMessage() const + { + return m_description; + } + + int line() const + { + return m_sourceLocation.line(); + } + + int column() const + { + return m_sourceLocation.column(); + } + + protected: + virtual void handleMessage(QtMsgType type, const QString &description, const QUrl &identifier, const QSourceLocation &sourceLocation) + { + Q_UNUSED(type); + Q_UNUSED(identifier); + + m_messageType = type; + m_description = description; + m_sourceLocation = sourceLocation; + } + + private: + QtMsgType m_messageType; + QString m_description; + QSourceLocation m_sourceLocation; +}; + +MainWindow::MainWindow() +{ + setupUi(this); + + new XmlSyntaxHighlighter(schemaView->document()); + new XmlSyntaxHighlighter(instanceEdit->document()); + + schemaSelection->addItem(tr("Contact Schema")); + schemaSelection->addItem(tr("Recipe Schema")); + schemaSelection->addItem(tr("Order Schema")); + + instanceSelection->addItem(tr("Valid Contact Instance")); + instanceSelection->addItem(tr("Invalid Contact Instance")); + + connect(schemaSelection, SIGNAL(currentIndexChanged(int)), SLOT(schemaSelected(int))); + connect(instanceSelection, SIGNAL(currentIndexChanged(int)), SLOT(instanceSelected(int))); + connect(validateButton, SIGNAL(clicked()), SLOT(validate())); + connect(instanceEdit, SIGNAL(textChanged()), SLOT(textChanged())); + + validationStatus->setAlignment(Qt::AlignCenter | Qt::AlignVCenter); + + schemaSelected(0); + instanceSelected(0); +} + +void MainWindow::schemaSelected(int index) +{ + instanceSelection->clear(); + if (index == 0) { + instanceSelection->addItem(tr("Valid Contact Instance")); + instanceSelection->addItem(tr("Invalid Contact Instance")); + } else if (index == 1) { + instanceSelection->addItem(tr("Valid Recipe Instance")); + instanceSelection->addItem(tr("Invalid Recipe Instance")); + } else if (index == 2) { + instanceSelection->addItem(tr("Valid Order Instance")); + instanceSelection->addItem(tr("Invalid Order Instance")); + } + textChanged(); + + QFile schemaFile(QString(":/schema_%1.xsd").arg(index)); + schemaFile.open(QIODevice::ReadOnly); + const QString schemaText(QString::fromLatin1(schemaFile.readAll())); + schemaView->setPlainText(schemaText); + + validate(); +} + +void MainWindow::instanceSelected(int index) +{ + QFile instanceFile(QString(":/instance_%1.xml").arg((2*schemaSelection->currentIndex()) + index)); + instanceFile.open(QIODevice::ReadOnly); + const QString instanceText(QString::fromLatin1(instanceFile.readAll())); + instanceEdit->setPlainText(instanceText); + + validate(); +} + +void MainWindow::validate() +{ + const QByteArray schemaData = schemaView->toPlainText().toLatin1(); + const QByteArray instanceData = instanceEdit->toPlainText().toLatin1(); + + MessageHandler messageHandler; + + QXmlSchema schema; + schema.setMessageHandler(&messageHandler); + + schema.load(schemaData, QUrl("http://dummySchemaUrl/")); + + bool errorOccurred = false; + if (!schema.isValid()) { + errorOccurred = true; + } else { + QXmlSchemaValidator validator(schema); + if (!validator.validate(instanceData, QUrl("http://dummyInstanceUrl"))) + errorOccurred = true; + } + + if (errorOccurred) { + validationStatus->setText(messageHandler.statusMessage()); + moveCursor(messageHandler.line(), messageHandler.column()); + } else { + validationStatus->setText(tr("validation successful")); + } + + QString styleSheet = QString("QLabel {background: %1; padding: 3px}").arg(errorOccurred ? QColor(Qt::red).lighter(160).name() : QColor(Qt::green).lighter(160).name()); + validationStatus->setStyleSheet(styleSheet); +} + +void MainWindow::textChanged() +{ + instanceEdit->setExtraSelections(QList()); +} + +void MainWindow::moveCursor(int line, int column) +{ + instanceEdit->moveCursor(QTextCursor::Start); + for (int i = 1; i < line; ++i) + instanceEdit->moveCursor(QTextCursor::Down); + + for (int i = 1; i < column; ++i) + instanceEdit->moveCursor(QTextCursor::Right); + + QList extraSelections; + QTextEdit::ExtraSelection selection; + + const QColor lineColor = QColor(Qt::red).lighter(160); + selection.format.setBackground(lineColor); + selection.format.setProperty(QTextFormat::FullWidthSelection, true); + selection.cursor = instanceEdit->textCursor(); + selection.cursor.clearSelection(); + extraSelections.append(selection); + + instanceEdit->setExtraSelections(extraSelections); + + instanceEdit->setFocus(); +} diff --git a/examples/xmlpatterns/schema/mainwindow.h b/examples/xmlpatterns/schema/mainwindow.h new file mode 100644 index 0000000..e5dc2df --- /dev/null +++ b/examples/xmlpatterns/schema/mainwindow.h @@ -0,0 +1,38 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include + +#include "ui_schema.h" + +//! [0] +class MainWindow : public QMainWindow, + private Ui::SchemaMainWindow +{ + Q_OBJECT + + public: + MainWindow(); + + private Q_SLOTS: + void schemaSelected(int index); + void instanceSelected(int index); + void validate(); + void textChanged(); + + private: + void moveCursor(int line, int column); +}; +//! [0] +#endif diff --git a/examples/xmlpatterns/schema/schema.pro b/examples/xmlpatterns/schema/schema.pro new file mode 100644 index 0000000..af32e0a --- /dev/null +++ b/examples/xmlpatterns/schema/schema.pro @@ -0,0 +1,11 @@ +QT += xmlpatterns +FORMS += schema.ui +HEADERS = mainwindow.h ../shared/xmlsyntaxhighlighter.h +RESOURCES = schema.qrc +SOURCES = main.cpp mainwindow.cpp ../shared/xmlsyntaxhighlighter.cpp +INCLUDEPATH += ../shared/ + +target.path = $$[QT_INSTALL_EXAMPLES]/xmlpatterns/schema +sources.files = $$SOURCES $$HEADERS $$RESOURCES *.pro *.xq *.html files +sources.path = $$[QT_INSTALL_EXAMPLES]/xmlpatterns/schema +INSTALLS += target sources diff --git a/examples/xmlpatterns/schema/schema.qrc b/examples/xmlpatterns/schema/schema.qrc new file mode 100644 index 0000000..eb7ddfd --- /dev/null +++ b/examples/xmlpatterns/schema/schema.qrc @@ -0,0 +1,13 @@ + + + files/contact.xsd + files/recipe.xsd + files/order.xsd + files/valid_contact.xml + files/invalid_contact.xml + files/valid_recipe.xml + files/invalid_recipe.xml + files/valid_order.xml + files/invalid_order.xml + + diff --git a/examples/xmlpatterns/schema/schema.ui b/examples/xmlpatterns/schema/schema.ui new file mode 100644 index 0000000..af7020a --- /dev/null +++ b/examples/xmlpatterns/schema/schema.ui @@ -0,0 +1,71 @@ + + + SchemaMainWindow + + + + 0 + 0 + 417 + 594 + + + + MainWindow + + + + + + + XML Schema Document: + + + + + + + + + + + + + XML Instance Document: + + + + + + + + + + + + + Status: + + + + + + + not validated + + + + + + + Validate + + + + + + + + + + diff --git a/examples/xmlpatterns/xmlpatterns.pro b/examples/xmlpatterns/xmlpatterns.pro index 1a57005..3ff3e35 100644 --- a/examples/xmlpatterns/xmlpatterns.pro +++ b/examples/xmlpatterns/xmlpatterns.pro @@ -2,7 +2,8 @@ TEMPLATE = subdirs SUBDIRS = recipes \ trafficinfo \ xquery \ - filetree + filetree \ + schema # This example depends on QtWebkit as well. contains(QT_CONFIG, webkit):SUBDIRS += qobjectxmlmodel diff --git a/src/xmlpatterns/Doxyfile b/src/xmlpatterns/Doxyfile index 60a6c77..83f7062 100644 --- a/src/xmlpatterns/Doxyfile +++ b/src/xmlpatterns/Doxyfile @@ -1157,7 +1157,7 @@ DOT_PATH = # contain dot files that are included in the documentation (see the # \dotfile command). -DOTFILE_DIRS = +DOTFILE_DIRS = schema/doc/ # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, which results in a white background. diff --git a/src/xmlpatterns/acceltree/qacceltree.cpp b/src/xmlpatterns/acceltree/qacceltree.cpp index 60e6e27..061021a 100644 --- a/src/xmlpatterns/acceltree/qacceltree.cpp +++ b/src/xmlpatterns/acceltree/qacceltree.cpp @@ -42,6 +42,7 @@ #include #include "qabstractxmlreceiver.h" +#include "qabstractxmlnodemodel_p.h" #include "qacceliterators_p.h" #include "qacceltree_p.h" #include "qatomicstring_p.h" @@ -55,6 +56,37 @@ QT_BEGIN_NAMESPACE using namespace QPatternist; +namespace QPatternist { + + class AccelTreePrivate : public QAbstractXmlNodeModelPrivate + { + public: + AccelTreePrivate(AccelTree *accelTree) + : m_accelTree(accelTree) + { + } + + virtual QSourceLocation sourceLocation(const QXmlNodeModelIndex &index) const + { + return m_accelTree->sourceLocation(index); + } + + private: + AccelTree *m_accelTree; + }; +} + +AccelTree::AccelTree(const QUrl &docURI, const QUrl &bURI) + : QAbstractXmlNodeModel(new AccelTreePrivate(this)) + , m_documentURI(docURI) + , m_baseURI(bURI) +{ + /* Pre-allocate at least a little bit. */ + // TODO. Do it according to what an average 4 KB doc contains. + basicData.reserve(100); + data.reserve(30); +} + void AccelTree::printStats(const NamePool::Ptr &np) const { Q_ASSERT(np); @@ -674,6 +706,17 @@ void AccelTree::copyNodeTo(const QXmlNodeModelIndex &node, } +QSourceLocation AccelTree::sourceLocation(const QXmlNodeModelIndex &index) const +{ + const PreNumber key = toPreNumber(index); + if (sourcePositions.contains(key)) { + const QPair position = sourcePositions.value(key); + return QSourceLocation(m_documentURI, position.first, position.second); + } else { + return QSourceLocation(); + } +} + void AccelTree::copyChildren(const QXmlNodeModelIndex &node, QAbstractXmlReceiver *const receiver, const NodeCopySettings &settings) const diff --git a/src/xmlpatterns/acceltree/qacceltree_p.h b/src/xmlpatterns/acceltree/qacceltree_p.h index 10320ba..4c0d844 100644 --- a/src/xmlpatterns/acceltree/qacceltree_p.h +++ b/src/xmlpatterns/acceltree/qacceltree_p.h @@ -91,6 +91,7 @@ namespace QPatternist */ class AccelTree : public QAbstractXmlNodeModel { + friend class AccelTreePrivate; public: using QAbstractXmlNodeModel::createIndex; @@ -99,15 +100,7 @@ namespace QPatternist typedef PreNumber PostNumber; typedef qint8 Depth; - inline AccelTree(const QUrl &docURI, - const QUrl &bURI) : m_documentURI(docURI), - m_baseURI(bURI) - { - /* Pre-allocate at least a little bit. */ - // TODO. Do it according to what an average 4 KB doc contains. - basicData.reserve(100); - data.reserve(30); - } + AccelTree(const QUrl &docURI, const QUrl &bURI); /** * @short Houses data for a node, and that all node kinds have. @@ -280,6 +273,7 @@ namespace QPatternist QHash data; QVector basicData; + QHash > sourcePositions; inline QUrl documentUri() const { @@ -381,6 +375,11 @@ namespace QPatternist private: /** + * Returns the source location for the object with the given @p index. + */ + QSourceLocation sourceLocation(const QXmlNodeModelIndex &index) const; + + /** * Copies the children of @p node to @p receiver. */ inline void copyChildren(const QXmlNodeModelIndex &node, diff --git a/src/xmlpatterns/acceltree/qacceltreebuilder.cpp b/src/xmlpatterns/acceltree/qacceltreebuilder.cpp index 5b16cc3..ddc118c 100644 --- a/src/xmlpatterns/acceltree/qacceltreebuilder.cpp +++ b/src/xmlpatterns/acceltree/qacceltreebuilder.cpp @@ -49,15 +49,17 @@ template AccelTreeBuilder::AccelTreeBuilder(const QUrl &docURI, const QUrl &baseURI, const NamePool::Ptr &np, - ReportContext *const context) : m_preNumber(-1) - , m_isPreviousAtomic(false) - , m_hasCharacters(false) - , m_isCharactersCompressed(false) - , m_namePool(np) - , m_document(new AccelTree(docURI, baseURI)) - , m_skippedDocumentNodes(0) - , m_documentURI(docURI) - , m_context(context) + ReportContext *const context, + Features features) : m_preNumber(-1) + , m_isPreviousAtomic(false) + , m_hasCharacters(false) + , m_isCharactersCompressed(false) + , m_namePool(np) + , m_document(new AccelTree(docURI, baseURI)) + , m_skippedDocumentNodes(0) + , m_documentURI(docURI) + , m_context(context) + , m_features(features) { Q_ASSERT(m_namePool); @@ -126,9 +128,18 @@ void AccelTreeBuilder::item(const Item &it) template void AccelTreeBuilder::startElement(const QXmlName &name) { + startElement(name, 1, 1); +} + +template +void AccelTreeBuilder::startElement(const QXmlName &name, qint64 line, qint64 column) +{ startStructure(); - m_document->basicData.append(AccelTree::BasicNodeData(currentDepth(), currentParent(), QXmlNodeModelIndex::Element, -1, name)); + AccelTree::BasicNodeData data(currentDepth(), currentParent(), QXmlNodeModelIndex::Element, -1, name); + m_document->basicData.append(data); + if (m_features & SourceLocationsFeature) + m_document->sourcePositions.insert(m_document->maximumPreNumber(), qMakePair(line, column)); ++m_preNumber; m_ancestors.push(m_preNumber); diff --git a/src/xmlpatterns/acceltree/qacceltreebuilder_p.h b/src/xmlpatterns/acceltree/qacceltreebuilder_p.h index 653eb85..91e8d68 100644 --- a/src/xmlpatterns/acceltree/qacceltreebuilder_p.h +++ b/src/xmlpatterns/acceltree/qacceltreebuilder_p.h @@ -90,15 +90,27 @@ namespace QPatternist typedef QExplicitlySharedDataPointer Ptr; /** + * Describes the memory relevant features the builder shall support. + */ + enum Feature + { + NoneFeature, ///< No special features are enabled. + SourceLocationsFeature = 1 ///< The accel tree builder will store source locations for each start element. + }; + Q_DECLARE_FLAGS(Features, Feature) + + /** * @param context may be @c null. */ AccelTreeBuilder(const QUrl &docURI, const QUrl &baseURI, const NamePool::Ptr &np, - ReportContext *const context); + ReportContext *const context, + Features features = NoneFeature); virtual void startDocument(); virtual void endDocument(); virtual void startElement(const QXmlName &name); + void startElement(const QXmlName &name, qint64 line, qint64 column); virtual void endElement(); virtual void attribute(const QXmlName &name, const QStringRef &value); virtual void characters(const QStringRef &ch); @@ -175,8 +187,13 @@ namespace QPatternist * a member. */ ReportContext *const m_context; + + Features m_features; }; + Q_DECLARE_OPERATORS_FOR_FLAGS(AccelTreeBuilder::Features) + Q_DECLARE_OPERATORS_FOR_FLAGS(AccelTreeBuilder::Features) + #include "qacceltreebuilder.cpp" } diff --git a/src/xmlpatterns/acceltree/qacceltreeresourceloader.cpp b/src/xmlpatterns/acceltree/qacceltreeresourceloader.cpp index 4a5c219..7c3d2c0 100644 --- a/src/xmlpatterns/acceltree/qacceltreeresourceloader.cpp +++ b/src/xmlpatterns/acceltree/qacceltreeresourceloader.cpp @@ -46,7 +46,6 @@ #include -#include "qacceltreebuilder_p.h" #include "qatomicstring_p.h" #include "qautoptr_p.h" #include "qcommonsequencetypes_p.h" @@ -57,14 +56,12 @@ QT_BEGIN_NAMESPACE using namespace QPatternist; -static inline uint qHash(const QUrl &uri) -{ - return qHash(uri.toString()); -} - AccelTreeResourceLoader::AccelTreeResourceLoader(const NamePool::Ptr &np, - const NetworkAccessDelegator::Ptr &manager) : m_namePool(np) - , m_networkAccessDelegator(manager) + const NetworkAccessDelegator::Ptr &manager, + AccelTreeBuilder::Features features) + : m_namePool(np) + , m_networkAccessDelegator(manager) + , m_features(features) { Q_ASSERT(m_namePool); Q_ASSERT(m_networkAccessDelegator); @@ -74,7 +71,7 @@ bool AccelTreeResourceLoader::retrieveDocument(const QUrl &uri, const ReportContext::Ptr &context) { Q_ASSERT(uri.isValid()); - AccelTreeBuilder builder(uri, uri, m_namePool, context.data()); + AccelTreeBuilder builder(uri, uri, m_namePool, context.data(), m_features); const AutoPtr reply(load(uri, m_networkAccessDelegator, context)); @@ -88,18 +85,35 @@ bool AccelTreeResourceLoader::retrieveDocument(const QUrl &uri, return success; } +bool AccelTreeResourceLoader::retrieveDocument(QIODevice *source, const QUrl &documentUri, const ReportContext::Ptr &context) +{ + Q_ASSERT(source); + Q_ASSERT(source->isReadable()); + Q_ASSERT(documentUri.isValid()); + + AccelTreeBuilder builder(documentUri, documentUri, m_namePool, context.data(), m_features); + + bool success = false; + success = streamToReceiver(source, &builder, m_namePool, context, documentUri); + + m_loadedDocuments.insert(documentUri, builder.builtDocument()); + + return success; +} + QNetworkReply *AccelTreeResourceLoader::load(const QUrl &uri, const NetworkAccessDelegator::Ptr &networkDelegator, - const ReportContext::Ptr &context) + const ReportContext::Ptr &context, ErrorHandling errorHandling) { return load(uri, networkDelegator->managerFor(uri), - context); + context, errorHandling); } QNetworkReply *AccelTreeResourceLoader::load(const QUrl &uri, QNetworkAccessManager *const networkManager, - const ReportContext::Ptr &context) + const ReportContext::Ptr &context, ErrorHandling errorHandling) + { Q_ASSERT(networkManager); Q_ASSERT(uri.isValid()); @@ -120,7 +134,7 @@ QNetworkReply *AccelTreeResourceLoader::load(const QUrl &uri, const QSourceLocation location(uri); - if(context) + if(context && (errorHandling == FailOnError)) context->error(errorMessage, ReportContext::FODC0002, location); return 0; @@ -130,7 +144,7 @@ QNetworkReply *AccelTreeResourceLoader::load(const QUrl &uri, } bool AccelTreeResourceLoader::streamToReceiver(QIODevice *const dev, - QAbstractXmlReceiver *const receiver, + AccelTreeBuilder *const receiver, const NamePool::Ptr &np, const ReportContext::Ptr &context, const QUrl &uri) @@ -154,7 +168,7 @@ bool AccelTreeResourceLoader::streamToReceiver(QIODevice *const dev, { /* Send the name. */ receiver->startElement(np->allocateQName(reader.namespaceUri().toString(), reader.name().toString(), - reader.prefix().toString())); + reader.prefix().toString()), reader.lineNumber(), reader.columnNumber()); /* Send namespace declarations. */ const QXmlStreamNamespaceDeclarations &nss = reader.namespaceDeclarations(); @@ -263,6 +277,22 @@ Item AccelTreeResourceLoader::openDocument(const QUrl &uri, } } +Item AccelTreeResourceLoader::openDocument(QIODevice *source, const QUrl &documentUri, + const ReportContext::Ptr &context) +{ + const AccelTree::Ptr doc(m_loadedDocuments.value(documentUri)); + + if(doc) + return doc->root(QXmlNodeModelIndex()); /* Pass in dummy object. We know AccelTree doesn't use it. */ + else + { + if(retrieveDocument(source, documentUri, context)) + return m_loadedDocuments.value(documentUri)->root(QXmlNodeModelIndex()); /* Pass in dummy object. We know AccelTree doesn't use it. */ + else + return Item(); + } +} + SequenceType::Ptr AccelTreeResourceLoader::announceDocument(const QUrl &uri, const Usage) { // TODO deal with the usage thingy diff --git a/src/xmlpatterns/acceltree/qacceltreeresourceloader_p.h b/src/xmlpatterns/acceltree/qacceltreeresourceloader_p.h index 863fd65..56f547a 100644 --- a/src/xmlpatterns/acceltree/qacceltreeresourceloader_p.h +++ b/src/xmlpatterns/acceltree/qacceltreeresourceloader_p.h @@ -52,12 +52,12 @@ #ifndef Patternist_AccelTreeResourceLoader_H #define Patternist_AccelTreeResourceLoader_H -#include #include #include #include "qabstractxmlreceiver.h" #include "qacceltree_p.h" +#include "qacceltreebuilder_p.h" #include "qdeviceresourceloader_p.h" #include "qnamepool_p.h" #include "qnetworkaccessdelegator_p.h" @@ -115,13 +115,25 @@ namespace QPatternist { public: /** + * Describes the behaviour of the resource loader in case of an + * error. + */ + enum ErrorHandling + { + FailOnError, ///< The resource loader will report the error via the report context. + ContinueOnError ///< The resource loader will report no error and return an empty QNetworkReply. + }; + + /** * AccelTreeResourceLoader does not own @p context. */ AccelTreeResourceLoader(const NamePool::Ptr &np, - const NetworkAccessDelegator::Ptr &networkDelegator); + const NetworkAccessDelegator::Ptr &networkDelegator, AccelTreeBuilder::Features = AccelTreeBuilder::NoneFeature); virtual Item openDocument(const QUrl &uri, const ReportContext::Ptr &context); + virtual Item openDocument(QIODevice *source, const QUrl &documentUri, + const ReportContext::Ptr &context); virtual SequenceType::Ptr announceDocument(const QUrl &uri, const Usage usageHint); virtual bool isDocumentAvailable(const QUrl &uri); @@ -133,7 +145,6 @@ namespace QPatternist const ReportContext::Ptr &context, const SourceLocationReflection *const where); - /** * @short Helper function that do NetworkAccessDelegator::get(), but * does it blocked. @@ -149,14 +160,14 @@ namespace QPatternist */ static QNetworkReply *load(const QUrl &uri, QNetworkAccessManager *const networkManager, - const ReportContext::Ptr &context); + const ReportContext::Ptr &context, ErrorHandling handling = FailOnError); /** * @overload */ static QNetworkReply *load(const QUrl &uri, const NetworkAccessDelegator::Ptr &networkDelegator, - const ReportContext::Ptr &context); + const ReportContext::Ptr &context, ErrorHandling handling = FailOnError); /** * @short Returns the URIs this AccelTreeResourceLoader has loaded @@ -165,14 +176,17 @@ namespace QPatternist virtual QSet deviceURIs() const; virtual void clear(const QUrl &uri); + private: static bool streamToReceiver(QIODevice *const dev, - QAbstractXmlReceiver *const receiver, + AccelTreeBuilder *const receiver, const NamePool::Ptr &np, const ReportContext::Ptr &context, const QUrl &uri); bool retrieveDocument(const QUrl &uri, const ReportContext::Ptr &context); + bool retrieveDocument(QIODevice *source, const QUrl &documentUri, + const ReportContext::Ptr &context); /** * If @p context is @c null, no error reporting should be done. */ @@ -185,6 +199,7 @@ namespace QPatternist const NamePool::Ptr m_namePool; const NetworkAccessDelegator::Ptr m_networkAccessDelegator; QHash, QString> m_unparsedTexts; + AccelTreeBuilder::Features m_features; }; } diff --git a/src/xmlpatterns/api/api.pri b/src/xmlpatterns/api/api.pri index a0298f2..9fcc2f5 100644 --- a/src/xmlpatterns/api/api.pri +++ b/src/xmlpatterns/api/api.pri @@ -3,11 +3,13 @@ HEADERS += $$PWD/qabstractxmlforwarditerator_p.h \ $$PWD/qabstracturiresolver.h \ $$PWD/qabstractxmlnodemodel.h \ $$PWD/qabstractxmlnodemodel_p.h \ + $$PWD/qabstractxmlpullprovider_p.h \ $$PWD/qabstractxmlreceiver.h \ $$PWD/qabstractxmlreceiver_p.h \ $$PWD/qdeviceresourceloader_p.h \ $$PWD/qiodevicedelegate_p.h \ $$PWD/qnetworkaccessdelegator_p.h \ + $$PWD/qpullbridge_p.h \ $$PWD/qresourcedelegator_p.h \ $$PWD/qsimplexmlnodemodel.h \ $$PWD/qsourcelocation.h \ @@ -20,6 +22,10 @@ HEADERS += $$PWD/qabstractxmlforwarditerator_p.h \ $$PWD/qxmlquery_p.h \ $$PWD/qxmlresultitems.h \ $$PWD/qxmlresultitems_p.h \ + $$PWD/qxmlschema.h \ + $$PWD/qxmlschema_p.h \ + $$PWD/qxmlschemavalidator.h \ + $$PWD/qxmlschemavalidator_p.h \ $$PWD/qxmlserializer.h \ $$PWD/qxmlserializer_p.h \ $$PWD/../../../tools/xmlpatterns/qcoloringmessagehandler_p.h \ @@ -29,9 +35,11 @@ SOURCES += $$PWD/qvariableloader.cpp \ $$PWD/qabstractmessagehandler.cpp \ $$PWD/qabstracturiresolver.cpp \ $$PWD/qabstractxmlnodemodel.cpp \ + $$PWD/qabstractxmlpullprovider.cpp \ $$PWD/qabstractxmlreceiver.cpp \ $$PWD/qiodevicedelegate.cpp \ $$PWD/qnetworkaccessdelegator.cpp \ + $$PWD/qpullbridge.cpp \ $$PWD/qresourcedelegator.cpp \ $$PWD/qsimplexmlnodemodel.cpp \ $$PWD/qsourcelocation.cpp \ @@ -41,6 +49,9 @@ SOURCES += $$PWD/qvariableloader.cpp \ $$PWD/qxmlnamepool.cpp \ $$PWD/qxmlquery.cpp \ $$PWD/qxmlresultitems.cpp \ + $$PWD/qxmlschema.cpp \ + $$PWD/qxmlschema_p.cpp \ + $$PWD/qxmlschemavalidator.cpp \ $$PWD/qxmlserializer.cpp \ $$PWD/../../../tools/xmlpatterns/qcoloringmessagehandler.cpp \ $$PWD/../../../tools/xmlpatterns/qcoloroutput.cpp diff --git a/src/xmlpatterns/api/qabstractxmlnodemodel.cpp b/src/xmlpatterns/api/qabstractxmlnodemodel.cpp index 0caa8c4..f535ec8 100644 --- a/src/xmlpatterns/api/qabstractxmlnodemodel.cpp +++ b/src/xmlpatterns/api/qabstractxmlnodemodel.cpp @@ -1666,4 +1666,20 @@ void QAbstractXmlNodeModel::copyNodeTo(const QXmlNodeModelIndex &node, "This function is not expected to be called."); } +/*! + Returns the source location for the object with the given \a index + or a default constructed QSourceLocation in case no location + information is available. + + \since TODO + */ +QSourceLocation QAbstractXmlNodeModel::sourceLocation(const QXmlNodeModelIndex &index) const +{ + // TODO: make this method virtual in Qt5 to allow source location support in custom models + if (d_ptr) + return d_ptr->sourceLocation(index); + else + return QSourceLocation(); +} + QT_END_NAMESPACE diff --git a/src/xmlpatterns/api/qabstractxmlnodemodel.h b/src/xmlpatterns/api/qabstractxmlnodemodel.h index 6c9574c..1d860a3 100644 --- a/src/xmlpatterns/api/qabstractxmlnodemodel.h +++ b/src/xmlpatterns/api/qabstractxmlnodemodel.h @@ -56,6 +56,7 @@ QT_MODULE(XmlPatterns) class QAbstractXmlNodeModel; class QAbstractXmlNodeModelPrivate; class QAbstractXmlReceiver; +class QSourceLocation; class QUrl; class QXmlName; class QXmlNodeModelIndex; @@ -69,6 +70,7 @@ namespace QPatternist class DynamicContext; class Item; class ItemType; + class XsdValidatedXmlNodeModel; template class ItemMappingIterator; template class SequenceMappingIterator; typedef QExplicitlySharedDataPointer ItemTypePtr; @@ -315,6 +317,8 @@ public: QAbstractXmlReceiver *const receiver, const NodeCopySettings &) const; + QSourceLocation sourceLocation(const QXmlNodeModelIndex &index) const; + protected: virtual QXmlNodeModelIndex nextFromSimpleAxis(SimpleAxis axis, const QXmlNodeModelIndex &origin) const = 0; @@ -343,6 +347,7 @@ protected: private: friend class QPatternist::ItemMappingIterator >; friend class QPatternist::SequenceMappingIterator; + friend class QPatternist::XsdValidatedXmlNodeModel; inline QExplicitlySharedDataPointer > mapToSequence(const QXmlNodeModelIndex &ni, const QExplicitlySharedDataPointer &) const; diff --git a/src/xmlpatterns/api/qabstractxmlnodemodel_p.h b/src/xmlpatterns/api/qabstractxmlnodemodel_p.h index 16ce613..0ab1b26 100644 --- a/src/xmlpatterns/api/qabstractxmlnodemodel_p.h +++ b/src/xmlpatterns/api/qabstractxmlnodemodel_p.h @@ -52,6 +52,9 @@ #ifndef QABSTRACTXMLNODEMODEL_P_H #define QABSTRACTXMLNODEMODEL_P_H +#include "qabstractxmlnodemodel.h" +#include "qsourcelocation.h" + QT_BEGIN_HEADER QT_BEGIN_NAMESPACE @@ -62,6 +65,13 @@ public: virtual ~QAbstractXmlNodeModelPrivate() { } + + virtual QSourceLocation sourceLocation(const QXmlNodeModelIndex &index) const + { + Q_UNUSED(index); + + return QSourceLocation(); + } }; QT_END_NAMESPACE diff --git a/src/xmlpatterns/api/qabstractxmlpullprovider.cpp b/src/xmlpatterns/api/qabstractxmlpullprovider.cpp new file mode 100644 index 0000000..a80604b --- /dev/null +++ b/src/xmlpatterns/api/qabstractxmlpullprovider.cpp @@ -0,0 +1,147 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include + +#include "qxmlname.h" +#include "qnamepool_p.h" +#include "qabstractxmlpullprovider_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +// TODO have example where query selects, and the events for the result are indented + +/*! + \internal + \class AbstractXmlPullProvider + \brief The AbstractXmlPullProvider class provides a pull-based stream interface for the XPath Data Model. + \reentrant + \ingroup xml-tools + + AbstractXmlPullProvider allows a stream of items from the XPath Data Model -- essentially XML -- + to be iterated over. The subclass of AbstractXmlPullProvider provides the events, and the + user calling next() and so on, consumes them. AbstractXmlPullProvider can be considered + a forward-only, non-reversible iterator. + + Note that the content the events describes, are not necessarily a well-formed XML document, but + rather an instance of the XPath Data model, to be specific. For instance, maybe a pull provider + returns two atomic values, followed by an element tree, and at the end two document nodes. + + If you are subclassing AbstractXmlPullProvider, be careful to correctly implement + the behaviors, as described for the individual members and events. + + \sa AbstractXmlPullProvider::Event + */ + +/*! + \enum AbstractXmlPullProvider::Event + \value StartOfInput The value AbstractXmlPullProvider::current() returns before the first call to next(). + \value AtomicValue an atomic value such as an \c xs:integer, \c xs:hexBinary, or \c xs:dateTime. Atomic values + can only be top level items. + \value StartDocument Signals the start of a document node. Note that a AbstractXmlPullProvider can provide + a sequence of document nodes. + \value EndDocument Signals the end of a document node. StartDocument and EndDocument are always balanced + and always top-level events. For instance, StartDocument can never appear after any StartElement + events that hasn't been balanced by the corresponding amount of EndElement events. + \value StartElement Signals an element start tag. + \value EndElement Signals the end of an element. StartElement and EndElement events are always balanced. + \value Text Signals a text node. Adjacent text nodes cannot occur. + \value ProcessingInstruction A processing instruction. Its name is returned from name(), and its value in stringValue(). + \value Comment a comment node. Its value can be retrieved with stingValue(). + \value Attribute Signals an attribute node. Attribute events can only appear after Namespace events, or + if no such are sent, after the StartElement. In addition they must appear sequentially, + and each name must be unique. The ordering of attribute events is undefined and insignificant. + \value Namespace Signals a namespace binding. They occur very infrequently and are not needed for attributes + and elements. Namespace events can only appear after the StartElement event. The + ordering of namespace events is undefined and insignificant. + \value EndOfInput When next() is called after the last event, EndOfInput is returned. + + \sa AbstractXmlPullProvider::current() + */ + +/*! + Constucts a AbstractXmlPullProvider instance. + */ +AbstractXmlPullProvider::AbstractXmlPullProvider() +{ +} + +/*! + Destructs this AbstractXmlPullProvider. + */ +AbstractXmlPullProvider::~AbstractXmlPullProvider() +{ +} + +/*! + \fn Event AbstractXmlPullProvider::next() = 0; + Advances this AbstractXmlPullProvider, and returns the new event. + + \sa current() + */ + +/*! + \fn Event AbstractXmlPullProvider::current() const = 0; + Returns the event that next() returned the last time it was called. It doesn't + alter this AbstractXmlPullProvider. + + current() may not modify this AbstractXmlPullProvider's state. Subsequent calls to current() + must return the same value. + + \sa AbstractXmlPullProvider::Event + */ + +/*! + \fn QName AbstractXmlPullProvider::name() const = 0; + If the current event is StartElement, + EndElement, ProcessingInstruction, Attribute, or Namespace, the node's name is returned. + + If the current event is ProcessingInstruction, + the processing instruction target is in in the local name. + + If the current event is Namespace, the name's namespace URI is the namespace, and + the local name is the prefix the name is binding to. + + In all other cases, an invalid QName is returned. + */ + +/*! + \fn QVariant AbstractXmlPullProvider::atomicValue() const = 0; + + If current() event is AtomicValue, the atomic value is returned as a QVariant. + In all other cases, this function returns a null QVariant. + */ + +/*! + \fn QString AbstractXmlPullProvider::stringValue() const = 0; + + If current() is Text, the text node's value is returned. + + If the current() event is Comment, its value is returned. The subclasser guarantees + it does not contain the string "-->". + + If the current() event is ProcessingInstruction, its data is returned. The subclasser + guarantees the data does not contain the string "?>". + + In other cases, it returns a default constructed string. + */ + +/*! + \fn QHash AbstractXmlPullProvider::attributes() = 0; + + If the current() is Element, the attributes of the element are returned, + an empty list of attributes otherwise. + */ + +QT_END_NAMESPACE + diff --git a/src/xmlpatterns/api/qabstractxmlpullprovider_p.h b/src/xmlpatterns/api/qabstractxmlpullprovider_p.h new file mode 100644 index 0000000..d05e649 --- /dev/null +++ b/src/xmlpatterns/api/qabstractxmlpullprovider_p.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef QABSTRACTXMLPULLPROVIDER_H +#define QABSTRACTXMLPULLPROVIDER_H + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QXmlItem; +class QXmlName; +class QString; +class QVariant; +template class QHash; + +namespace QPatternist +{ + class AbstractXmlPullProviderPrivate; + + class AbstractXmlPullProvider + { + public: + AbstractXmlPullProvider(); + virtual ~AbstractXmlPullProvider(); + + enum Event + { + StartOfInput = 1, + AtomicValue = 1 << 1, + StartDocument = 1 << 2, + EndDocument = 1 << 3, + StartElement = 1 << 4, + EndElement = 1 << 5, + Text = 1 << 6, + ProcessingInstruction = 1 << 7, + Comment = 1 << 8, + Attribute = 1 << 9, + Namespace = 1 << 10, + EndOfInput = 1 << 11 + }; + + virtual Event next() = 0; + virtual Event current() const = 0; + virtual QXmlName name() const = 0; + virtual QVariant atomicValue() const = 0; + virtual QString stringValue() const = 0; + + virtual QHash attributes() = 0; + virtual QHash attributeItems() = 0; + + /* *** The functions below are internal. */ + private: + Q_DISABLE_COPY(AbstractXmlPullProvider) + AbstractXmlPullProviderPrivate *d; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/api/qpullbridge.cpp b/src/xmlpatterns/api/qpullbridge.cpp new file mode 100644 index 0000000..f347339 --- /dev/null +++ b/src/xmlpatterns/api/qpullbridge.cpp @@ -0,0 +1,202 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include + +#include "qabstractxmlnodemodel_p.h" +#include "qitemmappingiterator_p.h" +#include "qitem_p.h" +#include "qxmlname.h" +#include "qxmlquery_p.h" + +#include "qpullbridge_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +/*! + \brief Bridges a QPatternist::SequenceIterator to QAbstractXmlPullProvider. + \class QPatternist::PullBridge + \internal + \reentrant + \ingroup xml-tools + + The approach of this class is rather straight forward since QPatternist::SequenceIterator + and QAbstractXmlPullProvider are conceptually similar. While QPatternist::SequenceIterator only + delivers top level items(since it's not an event stream, it's a list of items), PullBridge + needs to recursively iterate the children of nodes too, which is achieved through the + stack m_iterators. + */ + +AbstractXmlPullProvider::Event PullBridge::next() +{ + m_index = m_iterators.top().second->next(); + + if(!m_index.isNull()) + { + Item item(m_index); + + if(item && item.isAtomicValue()) + m_current = AtomicValue; + else + { + Q_ASSERT(item.isNode()); + + switch(m_index.kind()) + { + case QXmlNodeModelIndex::Attribute: + { + m_current = Attribute; + break; + } + case QXmlNodeModelIndex::Comment: + { + m_current = Comment; + break; + } + case QXmlNodeModelIndex::Element: + { + m_iterators.push(qMakePair(StartElement, m_index.iterate(QXmlNodeModelIndex::AxisChild))); + m_current = StartElement; + break; + } + case QXmlNodeModelIndex::Document: + { + m_iterators.push(qMakePair(StartDocument, m_index.iterate(QXmlNodeModelIndex::AxisChild))); + m_current = StartDocument; + break; + } + case QXmlNodeModelIndex::Namespace: + { + m_current = Namespace; + break; + } + case QXmlNodeModelIndex::ProcessingInstruction: + { + m_current = ProcessingInstruction; + break; + } + case QXmlNodeModelIndex::Text: + { + m_current = Text; + break; + } + } + } + } + else + { + if(m_iterators.isEmpty()) + m_current = EndOfInput; + else + { + switch(m_iterators.top().first) + { + case StartOfInput: + { + m_current = EndOfInput; + break; + } + case StartElement: + { + m_current = EndElement; + m_iterators.pop(); + break; + } + case StartDocument: + { + m_current = EndDocument; + m_iterators.pop(); + break; + } + default: + { + Q_ASSERT_X(false, Q_FUNC_INFO, + "Invalid value."); + m_current = EndOfInput; + } + } + } + + } + + return m_current; +} + +AbstractXmlPullProvider::Event PullBridge::current() const +{ + return m_current; +} + +QXmlNodeModelIndex PullBridge::index() const +{ + return m_index; +} + +QSourceLocation PullBridge::sourceLocation() const +{ + return m_index.model()->sourceLocation(m_index); +} + +QXmlName PullBridge::name() const +{ + return m_index.name(); +} + +QVariant PullBridge::atomicValue() const +{ + return QVariant(); +} + +QString PullBridge::stringValue() const +{ + return QString(); +} + +QHash PullBridge::attributes() +{ + Q_ASSERT(m_current == StartElement); + + QHash attributes; + + QXmlNodeModelIndex::Iterator::Ptr it = m_index.iterate(QXmlNodeModelIndex::AxisAttribute); + QXmlNodeModelIndex index = it->next(); + while (!index.isNull()) { + const Item attribute(index); + attributes.insert(index.name(), index.stringValue()); + + index = it->next(); + } + + return attributes; +} + +QHash PullBridge::attributeItems() +{ + Q_ASSERT(m_current == StartElement); + + QHash attributes; + + QXmlNodeModelIndex::Iterator::Ptr it = m_index.iterate(QXmlNodeModelIndex::AxisAttribute); + QXmlNodeModelIndex index = it->next(); + while (!index.isNull()) { + const Item attribute(index); + attributes.insert(index.name(), QXmlItem(index)); + + index = it->next(); + } + + return attributes; +} + +QT_END_NAMESPACE + diff --git a/src/xmlpatterns/api/qpullbridge_p.h b/src/xmlpatterns/api/qpullbridge_p.h new file mode 100644 index 0000000..823d27b --- /dev/null +++ b/src/xmlpatterns/api/qpullbridge_p.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef PATTERNIST_PULLBRIDGE_P_H +#define PATTERNIST_PULLBRIDGE_P_H + +#include +#include + +#include "qabstractxmlforwarditerator_p.h" +#include "qabstractxmlpullprovider_p.h" +#include "qitem_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + class PullBridge : public AbstractXmlPullProvider + { + public: + inline PullBridge(const QXmlNodeModelIndex::Iterator::Ptr &it) : m_current(StartOfInput) + { + Q_ASSERT(it); + m_iterators.push(qMakePair(StartOfInput, it)); + } + + virtual Event next(); + virtual Event current() const; + virtual QXmlName name() const; + /** + * Returns always an empty QVariant. + */ + virtual QVariant atomicValue() const; + virtual QString stringValue() const; + virtual QHash attributes(); + virtual QHash attributeItems(); + + QXmlNodeModelIndex index() const; + QSourceLocation sourceLocation() const; + + private: + typedef QStack > IteratorStack; + IteratorStack m_iterators; + QXmlNodeModelIndex m_index; + Event m_current; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/api/qresourcedelegator.cpp b/src/xmlpatterns/api/qresourcedelegator.cpp index 9d43419..fceef30 100644 --- a/src/xmlpatterns/api/qresourcedelegator.cpp +++ b/src/xmlpatterns/api/qresourcedelegator.cpp @@ -45,14 +45,6 @@ QT_BEGIN_NAMESPACE using namespace QPatternist; -/** - * Duplicated in qacceltreeresourceloader.cpp. - */ -static inline uint qHash(const QUrl &uri) -{ - return qHash(uri.toString()); -} - bool ResourceDelegator::isUnparsedTextAvailable(const QUrl &uri, const QString &encoding) { diff --git a/src/xmlpatterns/api/qxmlnamepool.cpp b/src/xmlpatterns/api/qxmlnamepool.cpp index 2337f8d..11274ab 100644 --- a/src/xmlpatterns/api/qxmlnamepool.cpp +++ b/src/xmlpatterns/api/qxmlnamepool.cpp @@ -96,6 +96,10 @@ QXmlNamePool::~QXmlNamePool() { } +QXmlNamePool::QXmlNamePool(QPatternist::NamePool *namePool) : d(QExplicitlySharedDataPointer(namePool)) +{ +} + /*! Assigns the \a other name pool to this one. */ diff --git a/src/xmlpatterns/api/qxmlnamepool.h b/src/xmlpatterns/api/qxmlnamepool.h index 3c1e112..87856ee 100644 --- a/src/xmlpatterns/api/qxmlnamepool.h +++ b/src/xmlpatterns/api/qxmlnamepool.h @@ -54,6 +54,8 @@ QT_MODULE(XmlPatterns) namespace QPatternist { class NamePool; + class XsdSchemaParser; + class XsdValidatingInstanceReader; } namespace QPatternistSDK @@ -73,10 +75,15 @@ public: QXmlNamePool &operator=(const QXmlNamePool &other); private: + QXmlNamePool(QPatternist::NamePool *namePool); friend class QXmlQueryPrivate; friend class QXmlQuery; + friend class QXmlSchemaPrivate; + friend class QXmlSchemaValidatorPrivate; friend class QXmlSerializerPrivate; friend class QXmlName; + friend class QPatternist::XsdSchemaParser; + friend class QPatternist::XsdValidatingInstanceReader; friend class QPatternistSDK::Global; QExplicitlySharedDataPointer d; }; diff --git a/src/xmlpatterns/api/qxmlquery.cpp b/src/xmlpatterns/api/qxmlquery.cpp index 5f9d87d..423da3e 100644 --- a/src/xmlpatterns/api/qxmlquery.cpp +++ b/src/xmlpatterns/api/qxmlquery.cpp @@ -231,6 +231,18 @@ QT_BEGIN_NAMESPACE \value XQuery10 XQuery 1.0. \value XSLT20 XSLT 2.0 + \omitvalue XmlSchema11IdentityConstraintSelector The selector, the restricted + XPath pattern found in W3C XML Schema 1.1 for uniqueness + contraints. Apart from restricting the syntax, the type check stage + for the expression assumes a sequence of nodes to be the focus. + \omitvalue XmlSchema11IdentityConstraintField The field, the restricted + XPath pattern found in W3C XML Schema 1.1 for uniqueness + contraints. Apart from restricting the syntax, the type check stage + for the expression assumes a sequence of nodes to be the focus. + \omitvalue XPath20 Signifies XPath 2.0. Has no effect in the public API, it's + used internally. As With XmlSchema11IdentityConstraintSelector and + XmlSchema11IdentityConstraintField, the type check stage + for the expression assumes a sequence of nodes to be the focus. \sa setQuery() */ diff --git a/src/xmlpatterns/api/qxmlquery.h b/src/xmlpatterns/api/qxmlquery.h index 138819c..c9f949e 100644 --- a/src/xmlpatterns/api/qxmlquery.h +++ b/src/xmlpatterns/api/qxmlquery.h @@ -71,6 +71,8 @@ namespace QPatternistSDK namespace QPatternist { + class XsdSchemaParser; + class XsdValidatingInstanceReader; class VariableLoader; }; @@ -79,8 +81,11 @@ class Q_XMLPATTERNS_EXPORT QXmlQuery public: enum QueryLanguage { - XQuery10 = 1, - XSLT20 = 2 + XQuery10 = 1, + XSLT20 = 2, + XmlSchema11IdentityConstraintSelector = 1024, + XmlSchema11IdentityConstraintField = 2048, + XPath20 = 4096 }; QXmlQuery(); @@ -135,6 +140,8 @@ private: friend class QXmlName; friend class QXmlSerializer; friend class QPatternistSDK::TestCase; + friend class QPatternist::XsdSchemaParser; + friend class QPatternist::XsdValidatingInstanceReader; friend class QPatternist::VariableLoader; template friend bool setFocusHelper(QXmlQuery *const queryInstance, const TInputType &focusValue); diff --git a/src/xmlpatterns/api/qxmlquery_p.h b/src/xmlpatterns/api/qxmlquery_p.h index c8ed441..7f58f97 100644 --- a/src/xmlpatterns/api/qxmlquery_p.h +++ b/src/xmlpatterns/api/qxmlquery_p.h @@ -142,13 +142,10 @@ public: if(!m_functionFactory) { - if(queryLanguage == QXmlQuery::XQuery10) - m_functionFactory = QPatternist::FunctionFactoryCollection::xpath20Factory(namePool.d); - else - { - Q_ASSERT(queryLanguage == QXmlQuery::XSLT20); + if(queryLanguage == QXmlQuery::XSLT20) m_functionFactory = QPatternist::FunctionFactoryCollection::xslt20Factory(namePool.d); - } + else + m_functionFactory = QPatternist::FunctionFactoryCollection::xpath20Factory(namePool.d); } const QPatternist::GenericStaticContext::Ptr genericStaticContext(new QPatternist::GenericStaticContext(namePool.d, @@ -164,6 +161,14 @@ public: if(!contextItem.isNull()) m_staticContext = QPatternist::StaticContext::Ptr(new QPatternist::StaticFocusContext(QPatternist::AtomicValue::qtToXDMType(contextItem), m_staticContext)); + else if( queryLanguage == QXmlQuery::XmlSchema11IdentityConstraintField + || queryLanguage == QXmlQuery::XmlSchema11IdentityConstraintSelector + || queryLanguage == QXmlQuery::XPath20) + m_staticContext = QPatternist::StaticContext::Ptr(new QPatternist::StaticFocusContext(QPatternist::BuiltinTypes::node, m_staticContext)); + + for (int i = 0; i < m_additionalNamespaceBindings.count(); ++i) { + m_staticContext->namespaceBindings()->addBinding(m_additionalNamespaceBindings.at(i)); + } return m_staticContext; } @@ -278,6 +283,11 @@ public: return m_expr; } + inline void addAdditionalNamespaceBinding(const QXmlName &binding) + { + m_additionalNamespaceBindings.append(binding); + } + QXmlNamePool namePool; QPointer messageHandler; /** @@ -321,6 +331,8 @@ public: QPatternist::SequenceType::Ptr m_requiredType; QPatternist::FunctionFactory::Ptr m_functionFactory; QPatternist::NetworkAccessDelegator::Ptr m_networkAccessDelegator; + + QList m_additionalNamespaceBindings; }; QT_END_NAMESPACE diff --git a/src/xmlpatterns/api/qxmlschema.cpp b/src/xmlpatterns/api/qxmlschema.cpp new file mode 100644 index 0000000..55b96cd --- /dev/null +++ b/src/xmlpatterns/api/qxmlschema.cpp @@ -0,0 +1,229 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qxmlschema.h" +#include "qxmlschema_p.h" + +#include +#include + +/*! + \class QXmlSchema + + \brief The QXmlSchema class provides loading and validation of a W3C XML Schema. + + \reentrant + \since 4.X + \ingroup xml-tools + + The QXmlSchema class loads, compiles and validates W3C XML Schema files + that can be used further for validation of XML instance documents via + \l{QXmlSchemaValidator}. +*/ + +/*! + Constructs an invalid, empty schema that cannot be used until + setSchema() is called. + */ +QXmlSchema::QXmlSchema() + : d(new QXmlSchemaPrivate(QXmlNamePool())) +{ +} + +/*! + Constructs a QXmlSchema that is a copy of \a other. The new + instance will share resources with the existing schema + to the extent possible. + */ +QXmlSchema::QXmlSchema(const QXmlSchema &other) + : d(other.d) +{ +} + +/*! + Destroys this QXmlSchema. + */ +QXmlSchema::~QXmlSchema() +{ +} + +/*! + Sets this QXmlSchema to a schema loaded from the \a source + URI. + */ +void QXmlSchema::load(const QUrl &source) +{ + d->load(source, QString()); +} + +/*! + Sets this QXmlSchema to a schema read from the \a source + device. The device must have been opened with at least + QIODevice::ReadOnly. + + \a documentUri represents the schema obtained from the \a source + device. It is the base URI of the schema, that is used + internally to resolve relative URIs that appear in the schema, and + for message reporting. + + If \a source is \c null or not readable, or if \a documentUri is not + a valid URI, behavior is undefined. + \sa isValid() + */ +void QXmlSchema::load(QIODevice *source, const QUrl &documentUri) +{ + d->load(source, documentUri, QString()); +} + +/*! + Sets this QXmlSchema to a schema read from the \a data + + \a documentUri represents the schema obtained from the \a data. + It is the base URI of the schema, that is used internally to + resolve relative URIs that appear in the schema, and + for message reporting. + + If \a documentUri is not a valid URI, behavior is undefined. + \sa isValid() + */ +void QXmlSchema::load(const QByteArray &data, const QUrl &documentUri) +{ + d->load(data, documentUri, QString()); +} + +/*! + Returns true if this schema is valid. Examples of invalid schemas + are ones that contain syntax errors or that do not conform the + W3C XML Schema specification. + */ +bool QXmlSchema::isValid() const +{ + return d->isValid(); +} + +/*! + Returns the name pool used by this QXmlSchema for constructing \l + {QXmlName} {names}. There is no setter for the name pool, because + mixing name pools causes errors due to name confusion. + */ +QXmlNamePool QXmlSchema::namePool() const +{ + return d->namePool(); +} + +/*! + Returns the document URI of the schema or an empty URI if no + schema has been set. + */ +QUrl QXmlSchema::documentUri() const +{ + return d->documentUri(); +} + +/*! + Changes the \l {QAbstractMessageHandler}{message handler} for this + QXmlSchema to \a handler. The schema sends all compile and + validation messages to this message handler. QXmlSchema does not take + ownership of \a handler. + + Normally, the default message handler is sufficient. It writes + compile and validation messages to \e stderr. The default message + handler includes color codes if \e stderr can render colors. + + When QXmlSchema calls QAbstractMessageHandler::message(), + the arguments are as follows: + + \table + \header + \o message() argument + \o Semantics + \row + \o QtMsgType type + \o Only QtWarningMsg and QtFatalMsg are used. The former + identifies a warning, while the latter identifies an error. + \row + \o const QString & description + \o An XHTML document which is the actual message. It is translated + into the current language. + \row + \o const QUrl &identifier + \o Identifies the error with a URI, where the fragment is + the error code, and the rest of the URI is the error namespace. + \row + \o const QSourceLocation & sourceLocation + \o Identifies where the error occurred. + \endtable + + */ +void QXmlSchema::setMessageHandler(QAbstractMessageHandler *handler) +{ + d->setMessageHandler(handler); +} + +/*! + Returns the message handler that handles compile and validation + messages for this QXmlSchema. + */ +QAbstractMessageHandler *QXmlSchema::messageHandler() const +{ + return d->messageHandler(); +} + +/*! + Sets the URI resolver to \a resolver. QXmlSchema does not take + ownership of \a resolver. + + \sa uriResolver() + */ +void QXmlSchema::setUriResolver(QAbstractUriResolver *resolver) +{ + d->setUriResolver(resolver); +} + +/*! + Returns the schema's URI resolver. If no URI resolver has been set, + QtXmlPatterns will use the URIs in queries as they are. + + The URI resolver provides a level of abstraction, or \e{polymorphic + URIs}. A resolver can rewrite \e{logical} URIs to physical ones, or + it can translate obsolete or invalid URIs to valid ones. + + When QtXmlPatterns calls QAbstractUriResolver::resolve() the + absolute URI is the URI mandated by the schema specification, and the + relative URI is the URI specified by the user. + + \sa setUriResolver() + */ +QAbstractUriResolver *QXmlSchema::uriResolver() const +{ + return d->uriResolver(); +} + +/*! + Sets the network manager to \a manager. + QXmlSchema does not take ownership of \a manager. + + \sa networkAccessManager() + */ +void QXmlSchema::setNetworkAccessManager(QNetworkAccessManager *manager) +{ + d->setNetworkAccessManager(manager); +} + +/*! + Returns the network manager, or 0 if it has not been set. + + \sa setNetworkAccessManager() + */ +QNetworkAccessManager *QXmlSchema::networkAccessManager() const +{ + return d->networkAccessManager(); +} diff --git a/src/xmlpatterns/api/qxmlschema.h b/src/xmlpatterns/api/qxmlschema.h new file mode 100644 index 0000000..225cce2 --- /dev/null +++ b/src/xmlpatterns/api/qxmlschema.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#ifndef QXMLSCHEMA_H +#define QXMLSCHEMA_H + +#include +#include + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +QT_MODULE(XmlPatterns) + +class QAbstractMessageHandler; +class QAbstractUriResolver; +class QIODevice; +class QNetworkAccessManager; +class QUrl; +class QXmlNamePool; +class QXmlSchemaPrivate; + +class Q_XMLPATTERNS_EXPORT QXmlSchema +{ + friend class QXmlSchemaValidatorPrivate; + + public: + QXmlSchema(); + QXmlSchema(const QXmlSchema &other); + ~QXmlSchema(); + + void load(const QUrl &source); + void load(QIODevice *source, const QUrl &documentUri); + void load(const QByteArray &data, const QUrl &documentUri); + + bool isValid() const; + + QXmlNamePool namePool() const; + QUrl documentUri() const; + + void setMessageHandler(QAbstractMessageHandler *handler); + QAbstractMessageHandler *messageHandler() const; + + void setUriResolver(QAbstractUriResolver *resolver); + QAbstractUriResolver *uriResolver() const; + + void setNetworkAccessManager(QNetworkAccessManager *networkmanager); + QNetworkAccessManager *networkAccessManager() const; + + private: + QSharedDataPointer d; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/api/qxmlschema_p.cpp b/src/xmlpatterns/api/qxmlschema_p.cpp new file mode 100644 index 0000000..ebcccee --- /dev/null +++ b/src/xmlpatterns/api/qxmlschema_p.cpp @@ -0,0 +1,169 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qacceltreeresourceloader_p.h" +#include "qxmlschema.h" +#include "qxmlschema_p.h" + +#include +#include +#include + +QXmlSchemaPrivate::QXmlSchemaPrivate(const QXmlNamePool &namePool) + : m_namePool(namePool) + , m_userMessageHandler(0) + , m_uriResolver(0) + , m_userNetworkAccessManager(0) + , m_schemaContext(new QPatternist::XsdSchemaContext(m_namePool.d)) + , m_schemaParserContext(new QPatternist::XsdSchemaParserContext(m_namePool.d, m_schemaContext)) + , m_schemaIsValid(false) +{ + m_networkAccessManager = new QPatternist::ReferenceCountedValue(new QNetworkAccessManager()); + m_messageHandler = new QPatternist::ReferenceCountedValue(new QPatternist::ColoringMessageHandler()); +} + +QXmlSchemaPrivate::QXmlSchemaPrivate(const QPatternist::XsdSchemaContext::Ptr &schemaContext) + : m_namePool(QXmlNamePool(schemaContext->namePool().data())) + , m_userMessageHandler(0) + , m_uriResolver(0) + , m_userNetworkAccessManager(0) + , m_schemaContext(schemaContext) + , m_schemaParserContext(new QPatternist::XsdSchemaParserContext(m_namePool.d, m_schemaContext)) + , m_schemaIsValid(false) +{ + m_networkAccessManager = new QPatternist::ReferenceCountedValue(new QNetworkAccessManager()); + m_messageHandler = new QPatternist::ReferenceCountedValue(new QPatternist::ColoringMessageHandler()); +} + +QXmlSchemaPrivate::QXmlSchemaPrivate(const QXmlSchemaPrivate &other) + : QSharedData(other) +{ + m_namePool = other.m_namePool; + m_userMessageHandler = other.m_userMessageHandler; + m_uriResolver = other.m_uriResolver; + m_userNetworkAccessManager = other.m_userNetworkAccessManager; + m_messageHandler = other.m_messageHandler; + m_networkAccessManager = other.m_networkAccessManager; + + m_schemaContext = other.m_schemaContext; + m_schemaParserContext = other.m_schemaParserContext; + m_schemaIsValid = other.m_schemaIsValid; + m_documentUri = other.m_documentUri; +} + +void QXmlSchemaPrivate::load(const QUrl &source, const QString &targetNamespace) +{ + m_documentUri = source; + + m_schemaContext->setMessageHandler(messageHandler()); + m_schemaContext->setUriResolver(uriResolver()); + m_schemaContext->setNetworkAccessManager(networkAccessManager()); + + const QPatternist::AutoPtr reply(QPatternist::AccelTreeResourceLoader::load(source, m_schemaContext->networkAccessManager(), + m_schemaContext, QPatternist::AccelTreeResourceLoader::ContinueOnError)); + if (reply) + load(reply.data(), source, targetNamespace); +} + +void QXmlSchemaPrivate::load(const QByteArray &data, const QUrl &documentUri, const QString &targetNamespace) +{ + QByteArray localData(data); + + QBuffer buffer(&localData); + buffer.open(QIODevice::ReadOnly); + + load(&buffer, documentUri, targetNamespace); +} + +void QXmlSchemaPrivate::load(QIODevice *source, const QUrl &documentUri, const QString &targetNamespace) +{ + m_schemaParserContext = QPatternist::XsdSchemaParserContext::Ptr(new QPatternist::XsdSchemaParserContext(m_namePool.d, m_schemaContext)); + m_schemaIsValid = false; + + if (!source) { + qWarning("A null QIODevice pointer cannot be passed."); + return; + } + + if (!source->isReadable()) { + qWarning("The device must be readable."); + return; + } + + m_documentUri = documentUri; + m_schemaContext->setMessageHandler(messageHandler()); + m_schemaContext->setUriResolver(uriResolver()); + m_schemaContext->setNetworkAccessManager(networkAccessManager()); + + QPatternist::XsdSchemaParser parser(m_schemaContext, m_schemaParserContext, source); + parser.setDocumentURI(documentUri); + parser.setTargetNamespace(targetNamespace); + + try { + parser.parse(); + m_schemaParserContext->resolver()->resolve(); + + m_schemaIsValid = true; + } catch (QPatternist::Exception exception) { + m_schemaIsValid = false; + } +} + +bool QXmlSchemaPrivate::isValid() const +{ + return m_schemaIsValid; +} + +QXmlNamePool QXmlSchemaPrivate::namePool() const +{ + return m_namePool; +} + +QUrl QXmlSchemaPrivate::documentUri() const +{ + return m_documentUri; +} + +void QXmlSchemaPrivate::setMessageHandler(QAbstractMessageHandler *handler) +{ + m_userMessageHandler = handler; +} + +QAbstractMessageHandler *QXmlSchemaPrivate::messageHandler() const +{ + if (m_userMessageHandler) + return m_userMessageHandler; + + return m_messageHandler.data()->value; +} + +void QXmlSchemaPrivate::setUriResolver(QAbstractUriResolver *resolver) +{ + m_uriResolver = resolver; +} + +QAbstractUriResolver *QXmlSchemaPrivate::uriResolver() const +{ + return m_uriResolver; +} + +void QXmlSchemaPrivate::setNetworkAccessManager(QNetworkAccessManager *networkmanager) +{ + m_userNetworkAccessManager = networkmanager; +} + +QNetworkAccessManager *QXmlSchemaPrivate::networkAccessManager() const +{ + if (m_userNetworkAccessManager) + return m_userNetworkAccessManager; + + return m_networkAccessManager.data()->value; +} diff --git a/src/xmlpatterns/api/qxmlschema_p.h b/src/xmlpatterns/api/qxmlschema_p.h new file mode 100644 index 0000000..e625f1e --- /dev/null +++ b/src/xmlpatterns/api/qxmlschema_p.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef QXMLSCHEMA_P_H +#define QXMLSCHEMA_P_H + +#include "qabstractmessagehandler.h" +#include "qabstracturiresolver.h" +#include "qautoptr_p.h" +#include "qcoloringmessagehandler_p.h" +#include "qreferencecountedvalue_p.h" + +#include "qxsdschemacontext_p.h" +#include "qxsdschemaparser_p.h" +#include "qxsdschemaparsercontext_p.h" + +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QXmlSchemaPrivate : public QSharedData +{ + public: + QXmlSchemaPrivate(const QXmlNamePool &namePool); + QXmlSchemaPrivate(const QPatternist::XsdSchemaContext::Ptr &schemaContext); + QXmlSchemaPrivate(const QXmlSchemaPrivate &other); + + void load(const QUrl &source, const QString &targetNamespace); + void load(QIODevice *source, const QUrl &documentUri, const QString &targetNamespace); + void load(const QByteArray &data, const QUrl &documentUri, const QString &targetNamespace); + bool isValid() const; + QXmlNamePool namePool() const; + QUrl documentUri() const; + void setMessageHandler(QAbstractMessageHandler *handler); + QAbstractMessageHandler *messageHandler() const; + void setUriResolver(QAbstractUriResolver *resolver); + QAbstractUriResolver *uriResolver() const; + void setNetworkAccessManager(QNetworkAccessManager *networkmanager); + QNetworkAccessManager *networkAccessManager() const; + + QXmlNamePool m_namePool; + QAbstractMessageHandler* m_userMessageHandler; + QAbstractUriResolver* m_uriResolver; + QNetworkAccessManager* m_userNetworkAccessManager; + QPatternist::ReferenceCountedValue::Ptr m_messageHandler; + QPatternist::ReferenceCountedValue::Ptr m_networkAccessManager; + + QPatternist::XsdSchemaContext::Ptr m_schemaContext; + QPatternist::XsdSchemaParserContext::Ptr m_schemaParserContext; + bool m_schemaIsValid; + QUrl m_documentUri; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/api/qxmlschemavalidator.cpp b/src/xmlpatterns/api/qxmlschemavalidator.cpp new file mode 100644 index 0000000..aa80537 --- /dev/null +++ b/src/xmlpatterns/api/qxmlschemavalidator.cpp @@ -0,0 +1,264 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qxmlschemavalidator.h" +#include "qxmlschemavalidator_p.h" + +#include "qacceltreeresourceloader_p.h" +#include "qxmlschema.h" +#include "qxmlschema_p.h" +#include "qxsdvalidatinginstancereader_p.h" + +#include +#include +#include + +/*! + \class QXmlSchemaValidator + + \brief The QXmlSchemaValidator class validates XML instance documents against a W3C XML Schema. + + \reentrant + \since 4.X + \ingroup xml-tools + + The QXmlSchemaValidator class loads, parses an XML instance document and validates it + against a W3C XML Schema that has been compiled with \l{QXmlSchema}. +*/ + +/*! + Constructs a schema validator that will use \a schema for validation. + */ +QXmlSchemaValidator::QXmlSchemaValidator(const QXmlSchema &schema) + : d(new QXmlSchemaValidatorPrivate(schema)) +{ +} + +/*! + Destroys this QXmlSchemaValidator. + */ +QXmlSchemaValidator::~QXmlSchemaValidator() +{ + delete d; +} + +/*! + Sets the \a schema that shall be used for further validation. + */ +void QXmlSchemaValidator::setSchema(const QXmlSchema &schema) +{ + d->setSchema(schema); +} + +/*! + Validates the XML instance document read from \a data with the + given \a documentUri against the schema. + + Returns \c true if the XML instance document is valid according the + schema, \c false otherwise. + */ +bool QXmlSchemaValidator::validate(const QByteArray &data, const QUrl &documentUri) +{ + QByteArray localData(data); + + QBuffer buffer(&localData); + buffer.open(QIODevice::ReadOnly); + + return validate(&buffer, documentUri); +} + +/*! + Validates the XML instance document read from \a source against the schema. + + Returns \c true if the XML instance document is valid according the + schema, \c false otherwise. + */ +bool QXmlSchemaValidator::validate(const QUrl &source) +{ + d->m_context->setMessageHandler(messageHandler()); + d->m_context->setUriResolver(uriResolver()); + d->m_context->setNetworkAccessManager(networkAccessManager()); + + const QPatternist::AutoPtr reply(QPatternist::AccelTreeResourceLoader::load(source, d->m_context->networkAccessManager(), + d->m_context, QPatternist::AccelTreeResourceLoader::ContinueOnError)); + if (reply) + return validate(reply.data(), source); + else + return false; +} + +/*! + Validates the XML instance document read from \a source with the + given \a documentUri against the schema. + + Returns \c true if the XML instance document is valid according the + schema, \c false otherwise. + */ +bool QXmlSchemaValidator::validate(QIODevice *source, const QUrl &documentUri) +{ + if (!source) { + qWarning("A null QIODevice pointer cannot be passed."); + return false; + } + + if (!source->isReadable()) { + qWarning("The device must be readable."); + return false; + } + + d->m_context->setMessageHandler(messageHandler()); + d->m_context->setUriResolver(uriResolver()); + d->m_context->setNetworkAccessManager(networkAccessManager()); + + QPatternist::NetworkAccessDelegator::Ptr delegator(new QPatternist::NetworkAccessDelegator(d->m_context->networkAccessManager(), + d->m_context->networkAccessManager())); + + QPatternist::AccelTreeResourceLoader loader(d->m_context->namePool(), delegator, QPatternist::AccelTreeBuilder::SourceLocationsFeature); + + QPatternist::Item item; + try { + item = loader.openDocument(source, documentUri, d->m_context); + } catch (QPatternist::Exception exception) { + return false; + } + + QXmlNodeModelIndex index = item.asNode(); + const QAbstractXmlNodeModel *model = item.asNode().model(); + + QPatternist::XsdValidatedXmlNodeModel *validatedModel = new QPatternist::XsdValidatedXmlNodeModel(model); + + QPatternist::XsdValidatingInstanceReader reader(validatedModel, documentUri, d->m_context); + if (d->m_schema) + reader.addSchema(d->m_schema, d->m_schemaDocumentUri); + try { + reader.read(); + } catch (QPatternist::Exception exception) { + return false; + } + + return true; +} + +/*! + Returns the name pool used by this QXmlSchemaValidator for constructing \l + {QXmlName} {names}. There is no setter for the name pool, because + mixing name pools causes errors due to name confusion. + */ +QXmlNamePool QXmlSchemaValidator::namePool() const +{ + return d->m_namePool; +} + +/*! + Changes the \l {QAbstractMessageHandler}{message handler} for this + QXmlSchemaValidator to \a handler. The schema validator sends all parsing and + validation messages to this message handler. QXmlSchemaValidator does not take + ownership of \a handler. + + Normally, the default message handler is sufficient. It writes + compile and validation messages to \e stderr. The default message + handler includes color codes if \e stderr can render colors. + + When QXmlSchemaValidator calls QAbstractMessageHandler::message(), + the arguments are as follows: + + \table + \header + \o message() argument + \o Semantics + \row + \o QtMsgType type + \o Only QtWarningMsg and QtFatalMsg are used. The former + identifies a warning, while the latter identifies an error. + \row + \o const QString & description + \o An XHTML document which is the actual message. It is translated + into the current language. + \row + \o const QUrl &identifier + \o Identifies the error with a URI, where the fragment is + the error code, and the rest of the URI is the error namespace. + \row + \o const QSourceLocation & sourceLocation + \o Identifies where the error occurred. + \endtable + + */ +void QXmlSchemaValidator::setMessageHandler(QAbstractMessageHandler *handler) +{ + d->m_userMessageHandler = handler; +} + +/*! + Returns the message handler that handles parsing and validation + messages for this QXmlSchemaValidator. + */ +QAbstractMessageHandler *QXmlSchemaValidator::messageHandler() const +{ + if (d->m_userMessageHandler) + return d->m_userMessageHandler; + + return d->m_messageHandler.data()->value; +} + +/*! + Sets the URI resolver to \a resolver. QXmlSchemaValidator does not take + ownership of \a resolver. + + \sa uriResolver() + */ +void QXmlSchemaValidator::setUriResolver(QAbstractUriResolver *resolver) +{ + d->m_uriResolver = resolver; +} + +/*! + Returns the schema's URI resolver. If no URI resolver has been set, + QtXmlPatterns will use the URIs in queries as they are. + + The URI resolver provides a level of abstraction, or \e{polymorphic + URIs}. A resolver can rewrite \e{logical} URIs to physical ones, or + it can translate obsolete or invalid URIs to valid ones. + + When QtXmlPatterns calls QAbstractUriResolver::resolve() the + absolute URI is the URI mandated by the schema specification, and the + relative URI is the URI specified by the user. + + \sa setUriResolver() + */ +QAbstractUriResolver *QXmlSchemaValidator::uriResolver() const +{ + return d->m_uriResolver; +} + +/*! + Sets the network manager to \a manager. + QXmlSchemaValidator does not take ownership of \a manager. + + \sa networkAccessManager() + */ +void QXmlSchemaValidator::setNetworkAccessManager(QNetworkAccessManager *manager) +{ + d->m_userNetworkAccessManager = manager; +} + +/*! + Returns the network manager, or 0 if it has not been set. + + \sa setNetworkAccessManager() + */ +QNetworkAccessManager *QXmlSchemaValidator::networkAccessManager() const +{ + if (d->m_userNetworkAccessManager) + return d->m_userNetworkAccessManager; + + return d->m_networkAccessManager.data()->value; +} diff --git a/src/xmlpatterns/api/qxmlschemavalidator.h b/src/xmlpatterns/api/qxmlschemavalidator.h new file mode 100644 index 0000000..e643995 --- /dev/null +++ b/src/xmlpatterns/api/qxmlschemavalidator.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#ifndef QXMLSCHEMAVALIDATOR_H +#define QXMLSCHEMAVALIDATOR_H + +#include + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +QT_MODULE(XmlPatterns) + +class QAbstractMessageHandler; +class QAbstractUriResolver; +class QIODevice; +class QNetworkAccessManager; +class QUrl; +class QXmlNamePool; +class QXmlSchema; +class QXmlSchemaValidatorPrivate; + +class Q_XMLPATTERNS_EXPORT QXmlSchemaValidator +{ + public: + QXmlSchemaValidator(const QXmlSchema &schema); + ~QXmlSchemaValidator(); + + void setSchema(const QXmlSchema &schema); + + bool validate(const QUrl &source); + bool validate(QIODevice *source, const QUrl &documentUri); + bool validate(const QByteArray &data, const QUrl &documentUri); + + QXmlNamePool namePool() const; + + void setMessageHandler(QAbstractMessageHandler *handler); + QAbstractMessageHandler *messageHandler() const; + + void setUriResolver(QAbstractUriResolver *resolver); + QAbstractUriResolver *uriResolver() const; + + void setNetworkAccessManager(QNetworkAccessManager *networkmanager); + QNetworkAccessManager *networkAccessManager() const; + + private: + QXmlSchemaValidatorPrivate* const d; + + Q_DISABLE_COPY(QXmlSchemaValidator) +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/api/qxmlschemavalidator_p.h b/src/xmlpatterns/api/qxmlschemavalidator_p.h new file mode 100644 index 0000000..0990f73 --- /dev/null +++ b/src/xmlpatterns/api/qxmlschemavalidator_p.h @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef QXMLSCHEMAVALIDATOR_P_H +#define QXMLSCHEMAVALIDATOR_P_H + +#include "qabstractmessagehandler.h" +#include "qabstracturiresolver.h" +#include "qautoptr_p.h" +#include "qcoloringmessagehandler_p.h" +#include "qxmlschema.h" +#include "qxmlschema_p.h" + +#include "qxsdschemacontext_p.h" +#include "qxsdschema_p.h" + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QXmlSchemaValidatorPrivate +{ +public: + QXmlSchemaValidatorPrivate(const QXmlSchema &schema) + : m_namePool(schema.namePool()) + , m_userMessageHandler(0) + , m_uriResolver(0) + , m_userNetworkAccessManager(0) + { + setSchema(schema); + + const QXmlSchemaPrivate *p = schema.d; + + // initialize the environment properties with the ones from the schema + + if (p->m_userNetworkAccessManager) // schema has user defined network access manager + m_userNetworkAccessManager = p->m_userNetworkAccessManager; + else + m_networkAccessManager = p->m_networkAccessManager; + + if (p->m_userMessageHandler) // schema has user defined message handler + m_userMessageHandler = p->m_userMessageHandler; + else + m_messageHandler = p->m_messageHandler; + + m_uriResolver = p->m_uriResolver; + } + + void setSchema(const QXmlSchema &schema) + { + // use same name pool as the schema + m_namePool = schema.namePool(); + m_schema = schema.d->m_schemaParserContext->schema(); + m_schemaDocumentUri = schema.documentUri(); + + // create a new schema context + m_context = QPatternist::XsdSchemaContext::Ptr(new QPatternist::XsdSchemaContext(m_namePool.d)); + m_context->m_schemaTypeFactory = schema.d->m_schemaContext->m_schemaTypeFactory; + m_context->m_builtinTypesFacetList = schema.d->m_schemaContext->m_builtinTypesFacetList; + } + + QXmlNamePool m_namePool; + QAbstractMessageHandler* m_userMessageHandler; + QAbstractUriResolver* m_uriResolver; + QNetworkAccessManager* m_userNetworkAccessManager; + QPatternist::ReferenceCountedValue::Ptr m_messageHandler; + QPatternist::ReferenceCountedValue::Ptr m_networkAccessManager; + + QPatternist::XsdSchemaContext::Ptr m_context; + QPatternist::XsdSchema::Ptr m_schema; + QUrl m_schemaDocumentUri; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/common.pri b/src/xmlpatterns/common.pri index 2573a26..27253d8 100644 --- a/src/xmlpatterns/common.pri +++ b/src/xmlpatterns/common.pri @@ -10,6 +10,7 @@ INCLUDEPATH += $$PWD/acceltree \ $$PWD/iterators \ $$PWD/janitors \ $$PWD/parser \ + $$PWD/schema \ $$PWD/type \ $$PWD/utils diff --git a/src/xmlpatterns/data/data.pri b/src/xmlpatterns/data/data.pri index 99591d4..ccfed42 100644 --- a/src/xmlpatterns/data/data.pri +++ b/src/xmlpatterns/data/data.pri @@ -1,8 +1,8 @@ HEADERS += $$PWD/qabstractdatetime_p.h \ $$PWD/qabstractduration_p.h \ $$PWD/qabstractfloatcasters_p.h \ - $$PWD/qabstractfloat_p.h \ $$PWD/qabstractfloatmathematician_p.h \ + $$PWD/qabstractfloat_p.h \ $$PWD/qanyuri_p.h \ $$PWD/qatomiccaster_p.h \ $$PWD/qatomiccasters_p.h \ @@ -14,8 +14,8 @@ HEADERS += $$PWD/qabstractdatetime_p.h \ $$PWD/qbase64binary_p.h \ $$PWD/qboolean_p.h \ $$PWD/qcommonvalues_p.h \ + $$PWD/qcomparisonfactory_p.h \ $$PWD/qdate_p.h \ - $$PWD/qschemadatetime_p.h \ $$PWD/qdaytimeduration_p.h \ $$PWD/qdecimal_p.h \ $$PWD/qderivedinteger_p.h \ @@ -24,19 +24,21 @@ HEADERS += $$PWD/qabstractdatetime_p.h \ $$PWD/qgday_p.h \ $$PWD/qgmonthday_p.h \ $$PWD/qgmonth_p.h \ - $$PWD/qgyear_p.h \ $$PWD/qgyearmonth_p.h \ + $$PWD/qgyear_p.h \ $$PWD/qhexbinary_p.h \ $$PWD/qinteger_p.h \ $$PWD/qitem_p.h \ $$PWD/qnodebuilder_p.h \ - $$PWD/qschemanumeric_p.h \ $$PWD/qqnamevalue_p.h \ $$PWD/qresourceloader_p.h \ - $$PWD/qsorttuple.cpp \ + $$PWD/qschemadatetime_p.h \ + $$PWD/qschemanumeric_p.h \ $$PWD/qschematime_p.h \ + $$PWD/qsorttuple.cpp \ $$PWD/quntypedatomic_p.h \ $$PWD/qvalidationerror_p.h \ + $$PWD/qvaluefactory_p.h \ $$PWD/qyearmonthduration_p.h SOURCES += $$PWD/qabstractdatetime.cpp \ @@ -53,8 +55,8 @@ SOURCES += $$PWD/qabstractdatetime.cpp \ $$PWD/qbase64binary.cpp \ $$PWD/qboolean.cpp \ $$PWD/qcommonvalues.cpp \ + $$PWD/qcomparisonfactory.cpp \ $$PWD/qdate.cpp \ - $$PWD/qschemadatetime.cpp \ $$PWD/qdaytimeduration.cpp \ $$PWD/qdecimal.cpp \ $$PWD/qduration.cpp \ @@ -68,11 +70,13 @@ SOURCES += $$PWD/qabstractdatetime.cpp \ $$PWD/qitem.cpp \ $$PWD/qnodebuilder.cpp \ $$PWD/qnodemodel.cpp \ - $$PWD/qschemanumeric.cpp \ $$PWD/qqnamevalue.cpp \ $$PWD/qresourceloader.cpp \ - $$PWD/qsorttuple.cpp \ + $$PWD/qschemadatetime.cpp \ + $$PWD/qschemanumeric.cpp \ $$PWD/qschematime.cpp \ + $$PWD/qsorttuple.cpp \ $$PWD/quntypedatomic.cpp \ $$PWD/qvalidationerror.cpp \ + $$PWD/qvaluefactory.cpp \ $$PWD/qyearmonthduration.cpp diff --git a/src/xmlpatterns/data/qcomparisonfactory.cpp b/src/xmlpatterns/data/qcomparisonfactory.cpp new file mode 100644 index 0000000..7fe298b --- /dev/null +++ b/src/xmlpatterns/data/qcomparisonfactory.cpp @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qatomiccomparators_p.h" +#include "qatomicstring_p.h" +#include "qcomparisonplatform_p.h" +#include "qvaluefactory_p.h" + +#include "qcomparisonfactory_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +/** + * @short Helper class for ComparisonFactory::fromLexical() which exposes + * CastingPlatform appropriately. + * + * @relates ComparisonFactory + */ +class PerformComparison : public ComparisonPlatform + , public SourceLocationReflection +{ +public: + PerformComparison(const SourceLocationReflection *const sourceLocationReflection, + const AtomicComparator::Operator op) : m_sourceReflection(sourceLocationReflection) + , m_operator(op) + { + Q_ASSERT(m_sourceReflection); + } + + bool operator()(const AtomicValue::Ptr &operand1, + const AtomicValue::Ptr &operand2, + const SchemaType::Ptr &type, + const ReportContext::Ptr &context) + { + const ItemType::Ptr asItemType((AtomicType::Ptr(type))); + + /* One area where the Query Transform world differs from the Schema + * world is that @c xs:duration is not considedered comparable, because + * it's according to Schema is partially comparable. This means + * ComparisonPlatform::fetchComparator() flags it as impossible, and + * hence we need to override that. + * + * SchemaType::wxsTypeMatches() will return true for sub-types of @c + * xs:duration as well, but that's ok since AbstractDurationComparator + * works for them too. */ + if(BuiltinTypes::xsDuration->wxsTypeMatches(type)) + prepareComparison(AtomicComparator::Ptr(new AbstractDurationComparator())); + else if (BuiltinTypes::xsGYear->wxsTypeMatches(type) || + BuiltinTypes::xsGYearMonth->wxsTypeMatches(type) || + BuiltinTypes::xsGMonth->wxsTypeMatches(type) || + BuiltinTypes::xsGMonthDay->wxsTypeMatches(type) || + BuiltinTypes::xsGDay->wxsTypeMatches(type)) + prepareComparison(AtomicComparator::Ptr(new AbstractDateTimeComparator())); + else + prepareComparison(fetchComparator(asItemType, asItemType, context)); + + return flexibleCompare(operand1, operand2, context); + } + + const SourceLocationReflection *actualReflection() const + { + return m_sourceReflection; + } + + AtomicComparator::Operator operatorID() const + { + return m_operator; + } + +private: + const SourceLocationReflection *const m_sourceReflection; + const AtomicComparator::Operator m_operator; +}; + +bool ComparisonFactory::compare(const AtomicValue::Ptr &operand1, + const AtomicComparator::Operator op, + const AtomicValue::Ptr &operand2, + const SchemaType::Ptr &type, + const ReportContext::Ptr &context, + const SourceLocationReflection *const sourceLocationReflection) +{ + Q_ASSERT(operand1); + Q_ASSERT(operand2); + Q_ASSERT(context); + Q_ASSERT(sourceLocationReflection); + Q_ASSERT(type); + Q_ASSERT_X(type->category() == SchemaType::SimpleTypeAtomic, Q_FUNC_INFO, + "We can only compare atomic values."); + + return PerformComparison(sourceLocationReflection, op)(operand1, operand2, type, context); +} + +bool ComparisonFactory::constructAndCompare(const DerivedString::Ptr &operand1, + const AtomicComparator::Operator op, + const DerivedString::Ptr &operand2, + const SchemaType::Ptr &type, + const ReportContext::Ptr &context, + const SourceLocationReflection *const sourceLocationReflection) +{ + Q_ASSERT(operand1); + Q_ASSERT(operand2); + Q_ASSERT(context); + Q_ASSERT(sourceLocationReflection); + Q_ASSERT(type); + Q_ASSERT_X(type->category() == SchemaType::SimpleTypeAtomic, Q_FUNC_INFO, + "We can only compare atomic values."); + + const AtomicValue::Ptr value1 = ValueFactory::fromLexical(operand1->stringValue(), type, context, sourceLocationReflection); + const AtomicValue::Ptr value2 = ValueFactory::fromLexical(operand2->stringValue(), type, context, sourceLocationReflection); + + return compare(value1, op, value2, type, context, sourceLocationReflection); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/data/qcomparisonfactory_p.h b/src/xmlpatterns/data/qcomparisonfactory_p.h new file mode 100644 index 0000000..09fc50b --- /dev/null +++ b/src/xmlpatterns/data/qcomparisonfactory_p.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_ComparisonFactory_H +#define Patternist_ComparisonFactory_H + +#include "qatomiccomparator_p.h" +#include "qderivedstring_p.h" +#include "qitem_p.h" +#include "qreportcontext_p.h" +#include "qschematype_p.h" + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Provides compare(), which is a high-level helper function for + * comparing atomic values. + * + * This class wraps the helper class ComparisonPlatform with a more specific, + * high-level API. + * + * @see ComparisonPlatform + * @author Frans Englich + * @ingroup Patternist_schema + */ + class ComparisonFactory + { + public: + /** + * @short Returns the result of evaluating operator @p op applied to the atomic + * values @p operand1 and @p operand2. + * + * The caller guarantees that both values are of type @p type. + * + * ComparisonFactory does not take ownership of @p sourceLocationReflection. + */ + static bool compare(const AtomicValue::Ptr &operand1, + const AtomicComparator::Operator op, + const AtomicValue::Ptr &operand2, + const SchemaType::Ptr &type, + const ReportContext::Ptr &context, + const SourceLocationReflection *const sourceLocationReflection); + + /** + * @short Returns the result of evaluating operator @p op applied to the atomic + * values @p operand1 and @p operand2. + * + * In opposite to compare() it converts the operands from string type + * to @p type and compares these constructed types. + * + * The caller guarantees that both values are of type @p type. + * + * ComparisonFactory does not take ownership of @p sourceLocationReflection. + */ + static bool constructAndCompare(const DerivedString::Ptr &operand1, + const AtomicComparator::Operator op, + const DerivedString::Ptr &operand2, + const SchemaType::Ptr &type, + const ReportContext::Ptr &context, + const SourceLocationReflection *const sourceLocationReflection); + + private: + Q_DISABLE_COPY(ComparisonFactory) + }; +} + +QT_END_NAMESPACE +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/data/qitem_p.h b/src/xmlpatterns/data/qitem_p.h index 987a1c2..08b318d 100644 --- a/src/xmlpatterns/data/qitem_p.h +++ b/src/xmlpatterns/data/qitem_p.h @@ -128,6 +128,11 @@ namespace QPatternist typedef QExplicitlySharedDataPointer Ptr; /** + * A list if smart pointers wrapping AtomicValue instances. + */ + typedef QList List; + + /** * Determines whether this atomic value has an error. This is used * for implementing casting. * diff --git a/src/xmlpatterns/data/qvaluefactory.cpp b/src/xmlpatterns/data/qvaluefactory.cpp new file mode 100644 index 0000000..04df29d --- /dev/null +++ b/src/xmlpatterns/data/qvaluefactory.cpp @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qatomiccaster_p.h" +#include "qatomicstring_p.h" +#include "qcastingplatform_p.h" +#include "qvaluefactory_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +/** + * @short Helper class for ValueFactory::fromLexical() which exposes + * CastingPlatform appropriately. + * + * @relates ValueFactory + */ +class PerformValueConstruction : public CastingPlatform + , public SourceLocationReflection +{ +public: + PerformValueConstruction(const SourceLocationReflection *const sourceLocationReflection, + const SchemaType::Ptr &toType) : m_sourceReflection(sourceLocationReflection) + , m_targetType(AtomicType::Ptr(toType)) + { + Q_ASSERT(m_sourceReflection); + } + + AtomicValue::Ptr operator()(const AtomicValue::Ptr &lexicalValue, + const SchemaType::Ptr &type, + const ReportContext::Ptr &context) + { + prepareCasting(context, BuiltinTypes::xsString); + return AtomicValue::Ptr(const_cast(cast(lexicalValue, context).asAtomicValue())); + } + + const SourceLocationReflection *actualReflection() const + { + return m_sourceReflection; + } + + ItemType::Ptr targetType() const + { + return m_targetType; + } + +private: + const SourceLocationReflection *const m_sourceReflection; + const ItemType::Ptr m_targetType; +}; + +AtomicValue::Ptr ValueFactory::fromLexical(const QString &lexicalValue, + const SchemaType::Ptr &type, + const ReportContext::Ptr &context, + const SourceLocationReflection *const sourceLocationReflection) +{ + Q_ASSERT(context); + Q_ASSERT(type); + Q_ASSERT_X(type->category() == SchemaType::SimpleTypeAtomic, Q_FUNC_INFO, + "We can only construct for atomic values."); + + return PerformValueConstruction(sourceLocationReflection, type)(AtomicString::fromValue(lexicalValue), + type, + context); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/data/qvaluefactory_p.h b/src/xmlpatterns/data/qvaluefactory_p.h new file mode 100644 index 0000000..80b6207 --- /dev/null +++ b/src/xmlpatterns/data/qvaluefactory_p.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_ValueFactory_H +#define Patternist_ValueFactory_H + +#include "qitem_p.h" +#include "qreportcontext_p.h" +#include "qschematype_p.h" + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Provides fromLexical(), which allows instantiation of atomic + * values from arbitrary types. + * + * This class wraps the helper class CastingPlatform with a more specific, + * high-level API. + * + * @see CastingPlatform + * @author Frans Englich + * @ingroup Patternist_schema + */ + class ValueFactory + { + public: + /** + * @short Returns an AtomicValue of type @p type from the lexical space + * @p lexicalValue, and raise an error through @p context if that's + * impossible. + * + * ValueFactory does not take ownership of @p sourceLocationReflection. + */ + static AtomicValue::Ptr fromLexical(const QString &lexicalValue, + const SchemaType::Ptr &type, + const ReportContext::Ptr &context, + const SourceLocationReflection *const sourceLocationReflection); + + private: + Q_DISABLE_COPY(ValueFactory) + }; +} + +QT_END_NAMESPACE +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/environment/createReportContext.xsl b/src/xmlpatterns/environment/createReportContext.xsl index e648c56..1db00e7 100644 --- a/src/xmlpatterns/environment/createReportContext.xsl +++ b/src/xmlpatterns/environment/createReportContext.xsl @@ -242,6 +242,11 @@ namespace QPatternist */]]> enum ErrorCode { + /** + * XML Schema error code. + */ + XSDError, + diff --git a/src/xmlpatterns/environment/qreportcontext.cpp b/src/xmlpatterns/environment/qreportcontext.cpp index 9704a54..acd6be0 100644 --- a/src/xmlpatterns/environment/qreportcontext.cpp +++ b/src/xmlpatterns/environment/qreportcontext.cpp @@ -448,6 +448,7 @@ QString ReportContext::codeToString(const ReportContext::ErrorCode code) case XTTE1545: result = "XTTE1545"; break; case XTTE1550: result = "XTTE1550"; break; case XTTE1555: result = "XTTE1555"; break; + case XSDError: result = "XSDError"; break; } Q_ASSERT_X(result, Q_FUNC_INFO, "Unknown enum value."); diff --git a/src/xmlpatterns/environment/qreportcontext_p.h b/src/xmlpatterns/environment/qreportcontext_p.h index bea2a97..8864756 100644 --- a/src/xmlpatterns/environment/qreportcontext_p.h +++ b/src/xmlpatterns/environment/qreportcontext_p.h @@ -151,6 +151,10 @@ namespace QPatternist */ enum ErrorCode { + /** + * XML Schema error code. + */ + XSDError, /** * It is a static error if analysis of an expression relies on some diff --git a/src/xmlpatterns/expr/qcastingplatform.cpp b/src/xmlpatterns/expr/qcastingplatform.cpp index 9e96fd8..16a1d60 100644 --- a/src/xmlpatterns/expr/qcastingplatform.cpp +++ b/src/xmlpatterns/expr/qcastingplatform.cpp @@ -83,7 +83,7 @@ Item CastingPlatform::cast(const Item &sourceValue, else { bool castImpossible = false; - const AtomicCaster::Ptr caster(locateCaster(sourceValue.type(), context, castImpossible)); + const AtomicCaster::Ptr caster(locateCaster(sourceValue.type(), context, castImpossible, static_cast(this), targetType())); if(!issueError && castImpossible) { @@ -112,7 +112,7 @@ bool CastingPlatform::prepareCasting(const ReportContext: or numeric at compile time. We'll do lookup at runtime instead. */ bool castImpossible = false; - m_caster = locateCaster(sourceType, context, castImpossible); + m_caster = locateCaster(sourceType, context, castImpossible, static_cast(this), targetType()); return !castImpossible; } @@ -120,20 +120,22 @@ bool CastingPlatform::prepareCasting(const ReportContext: template AtomicCaster::Ptr CastingPlatform::locateCaster(const ItemType::Ptr &sourceType, const ReportContext::Ptr &context, - bool &castImpossible) const + bool &castImpossible, + const SourceLocationReflection *const location, + const ItemType::Ptr &targetType) { Q_ASSERT(sourceType); - Q_ASSERT(targetType()); + Q_ASSERT(targetType); const AtomicCasterLocator::Ptr locator(static_cast( - targetType().data())->casterLocator()); + targetType.data())->casterLocator()); if(!locator) { if(issueError) { context->error(QtXmlPatterns::tr("No casting is possible with %1 as the target type.") - .arg(formatType(context->namePool(), targetType())), - ReportContext::XPTY0004, static_cast(this)); + .arg(formatType(context->namePool(), targetType)), + ReportContext::XPTY0004, location); } else castImpossible = true; @@ -141,15 +143,15 @@ AtomicCaster::Ptr CastingPlatform::locateCaster(const Ite return AtomicCaster::Ptr(); } - const AtomicCaster::Ptr caster(static_cast(sourceType.data())->accept(locator, static_cast(this))); + const AtomicCaster::Ptr caster(static_cast(sourceType.data())->accept(locator, location)); if(!caster) { if(issueError) { context->error(QtXmlPatterns::tr("It is not possible to cast from %1 to %2.") .arg(formatType(context->namePool(), sourceType)) - .arg(formatType(context->namePool(), targetType())), - ReportContext::XPTY0004, static_cast(this)); + .arg(formatType(context->namePool(), targetType)), + ReportContext::XPTY0004, location); } else castImpossible = true; diff --git a/src/xmlpatterns/expr/qcastingplatform_p.h b/src/xmlpatterns/expr/qcastingplatform_p.h index 458e9eb..a0144b2 100644 --- a/src/xmlpatterns/expr/qcastingplatform_p.h +++ b/src/xmlpatterns/expr/qcastingplatform_p.h @@ -52,16 +52,17 @@ #ifndef Patternist_CastingPlatform_H #define Patternist_CastingPlatform_H +#include "qatomiccasterlocator_p.h" #include "qatomiccaster_p.h" -#include "qqnamevalue_p.h" #include "qatomicstring_p.h" -#include "qvalidationerror_p.h" -#include "qatomiccasterlocator_p.h" #include "qatomictype_p.h" #include "qbuiltintypes_p.h" #include "qcommonsequencetypes_p.h" -#include "qschematypefactory_p.h" #include "qpatternistlocale_p.h" +#include "qqnamevalue_p.h" +#include "qschematypefactory_p.h" +#include "qstaticcontext_p.h" +#include "qvalidationerror_p.h" QT_BEGIN_HEADER @@ -101,6 +102,7 @@ namespace QPatternist * function targetType() must be implemented such that CastingPlatform knows * what type it shall cast to. * + * @see ValueFactory * @author Frans Englich * @ingroup Patternist_expressions */ @@ -167,9 +169,16 @@ namespace QPatternist * * @p castImpossible is not initialized. Initialize it to @c false. */ - AtomicCaster::Ptr locateCaster(const ItemType::Ptr &sourceType, - const ReportContext::Ptr &context, - bool &castImpossible) const; + static AtomicCaster::Ptr locateCaster(const ItemType::Ptr &sourceType, + const ReportContext::Ptr &context, + bool &castImpossible, + const SourceLocationReflection *const location, + const ItemType::Ptr &targetType); + private: + inline Item castWithCaster(const Item &sourceValue, + const AtomicCaster::Ptr &caster, + const DynamicContext::Ptr &context) const; + inline ItemType::Ptr targetType() const { diff --git a/src/xmlpatterns/expr/qexpressionfactory.cpp b/src/xmlpatterns/expr/qexpressionfactory.cpp index ec86be0..b41b0de 100644 --- a/src/xmlpatterns/expr/qexpressionfactory.cpp +++ b/src/xmlpatterns/expr/qexpressionfactory.cpp @@ -81,9 +81,13 @@ Expression::Ptr ExpressionFactory::createExpression(const QString &expr, const QUrl &queryURI, const QXmlName &initialTemplateName) { - if(lang == QXmlQuery::XQuery10) + if(lang == QXmlQuery::XSLT20) { - return createExpression(Tokenizer::Ptr(new XQueryTokenizer(expr, queryURI)), + QByteArray query(expr.toUtf8()); + QBuffer buffer(&query); + buffer.open(QIODevice::ReadOnly); + + return createExpression(&buffer, context, lang, requiredType, @@ -92,12 +96,7 @@ Expression::Ptr ExpressionFactory::createExpression(const QString &expr, } else { - Q_ASSERT(lang == QXmlQuery::XSLT20); - QByteArray query(expr.toUtf8()); - QBuffer buffer(&query); - buffer.open(QIODevice::ReadOnly); - - return createExpression(&buffer, + return createExpression(Tokenizer::Ptr(new XQueryTokenizer(expr, queryURI)), context, lang, requiredType, @@ -118,16 +117,10 @@ Expression::Ptr ExpressionFactory::createExpression(QIODevice *const device, Tokenizer::Ptr tokenizer; - if(lang == QXmlQuery::XQuery10) - { - - tokenizer = Tokenizer::Ptr(new XQueryTokenizer(QString::fromUtf8(device->readAll()), queryURI)); - } - else - { - Q_ASSERT(lang == QXmlQuery::XSLT20); + if(lang == QXmlQuery::XSLT20) tokenizer = Tokenizer::Ptr(new XSLTTokenizer(device, queryURI, context, context->namePool())); - } + else + tokenizer = Tokenizer::Ptr(new XQueryTokenizer(QString::fromUtf8(device->readAll()), queryURI)); return createExpression(tokenizer, context, lang, requiredType, queryURI, initialTemplateName); } diff --git a/src/xmlpatterns/functions/qpatternplatform.cpp b/src/xmlpatterns/functions/qpatternplatform.cpp index 0052a07..d99bac5 100644 --- a/src/xmlpatterns/functions/qpatternplatform.cpp +++ b/src/xmlpatterns/functions/qpatternplatform.cpp @@ -168,8 +168,15 @@ void PatternPlatform::applyFlags(const Flags flags, QRegExp &patternP) // TODO Apply the other flags, like 'x'. } +QRegExp PatternPlatform::parsePattern(const QString &pattern, + const ReportContext::Ptr &context) const +{ + return parsePattern(pattern, context, this); +} + QRegExp PatternPlatform::parsePattern(const QString &patternP, - const DynamicContext::Ptr &context) const + const ReportContext::Ptr &context, + const SourceLocationReflection *const location) { if(patternP == QLatin1String("(.)\\3") || patternP == QLatin1String("\\3") || @@ -177,7 +184,7 @@ QRegExp PatternPlatform::parsePattern(const QString &patternP, { context->error(QLatin1String("We don't want to hang infinitely on K2-MatchesFunc-9, " "10 and 11. See Trolltech task 148505."), - ReportContext::FOER0000, this); + ReportContext::FOER0000, location); return QRegExp(); } @@ -189,14 +196,8 @@ QRegExp PatternPlatform::parsePattern(const QString &patternP, * QChar::category(). */ rewrittenPattern.replace(QLatin1String("[\\i-[:]]"), QLatin1String("[a-zA-Z_]")); rewrittenPattern.replace(QLatin1String("[\\c-[:]]"), QLatin1String("[a-zA-Z0-9_\\-\\.]")); - rewrittenPattern.replace(QLatin1String("\\i"), QLatin1String("[a-zA-Z:_]")); - rewrittenPattern.replace(QLatin1String("\\c"), QLatin1String("[a-zA-Z0-9:_\\-\\.]")); - rewrittenPattern.replace(QLatin1String("\\p{L}"), QLatin1String("[a-zA-Z]")); - rewrittenPattern.replace(QLatin1String("\\p{Lu}"), QLatin1String("[A-Z]")); - rewrittenPattern.replace(QLatin1String("\\p{Ll}"), QLatin1String("[a-z]")); - rewrittenPattern.replace(QLatin1String("\\p{Nd}"), QLatin1String("[0-9]")); - QRegExp retval(rewrittenPattern); + QRegExp retval(rewrittenPattern, Qt::CaseSensitive, QRegExp::W3CXmlSchema11); if(retval.isValid()) return retval; @@ -204,7 +205,7 @@ QRegExp PatternPlatform::parsePattern(const QString &patternP, { context->error(QtXmlPatterns::tr("%1 is an invalid regular expression pattern: %2") .arg(formatExpression(patternP), retval.errorString()), - ReportContext::FORX0002, this); + ReportContext::FORX0002, location); return QRegExp(); } } diff --git a/src/xmlpatterns/functions/qpatternplatform_p.h b/src/xmlpatterns/functions/qpatternplatform_p.h index ce0dbd4..28da452 100644 --- a/src/xmlpatterns/functions/qpatternplatform_p.h +++ b/src/xmlpatterns/functions/qpatternplatform_p.h @@ -122,6 +122,14 @@ namespace QPatternist */ inline int captureCount() const; + /** + * @short Parses pattern + */ + static QRegExp parsePattern(const QString &pattern, + const ReportContext::Ptr &context, + const SourceLocationReflection *const location); + + protected: /** * @short This constructor is protected, because this class is supposed to be sub-classed. @@ -146,14 +154,18 @@ namespace QPatternist }; typedef QFlags PreCompiledParts; + /** + * @short Calls the public parsePattern() function and passes in @c + * this as the location. + */ + inline QRegExp parsePattern(const QString &pattern, + const ReportContext::Ptr &context) const; + Q_DISABLE_COPY(PatternPlatform) Flags parseFlags(const QString &flags, const DynamicContext::Ptr &context) const; - QRegExp parsePattern(const QString &pattern, - const DynamicContext::Ptr &context) const; - static void applyFlags(const Flags flags, QRegExp &pattern); /** diff --git a/src/xmlpatterns/parser/qquerytransformparser.cpp b/src/xmlpatterns/parser/qquerytransformparser.cpp index 60e3a0c..b2f8cd2 100644 --- a/src/xmlpatterns/parser/qquerytransformparser.cpp +++ b/src/xmlpatterns/parser/qquerytransformparser.cpp @@ -300,11 +300,18 @@ static inline QSourceLocation fromYYLTYPE(const YYLTYPE &sourceLocator, } /** + * @internal + * @relates QXmlQuery + */ +typedef QFlags QueryLanguages; + +/** * @short Flags invalid expressions and declarations in the currently * parsed language. * - * Since this grammar is used for several languages: XQuery 1.0, XSL-T 2.0 and - * XPath 2.0 inside XSL-T, it is the union of all the constructs in these + * Since this grammar is used for several languages: XQuery 1.0, XSL-T 2.0, and + * XPath 2.0 inside XSL-T, and field and selector patterns in W3C XML Schema's + * identity constraints, it is the union of all the constructs in these * languages. However, when dealing with each language individually, we * regularly need to disallow some expressions, such as direct element * constructors when parsing XSL-T, or the typeswitch when parsing XPath. @@ -315,19 +322,46 @@ static inline QSourceLocation fromYYLTYPE(const YYLTYPE &sourceLocator, * instance the @c let clause, should not be flagged as an error, because it's * used for internal purposes. * - * Hence, this function is called from each expression and declaration which is - * unavailable in XPath. + * Hence, this function is called from each expression and declaration with @p + * allowedLanguages stating what languages it is allowed in. * * If @p isInternal is @c true, no error is raised. Otherwise, if the current - * language is not XQuery, an error is raised. + * language is not in @p allowedLanguages, an error is raised. */ -static void disallowedConstruct(const ParserContext *const parseInfo, - const YYLTYPE &sourceLocator, - const bool isInternal = false) +static void allowedIn(const QueryLanguages allowedLanguages, + const ParserContext *const parseInfo, + const YYLTYPE &sourceLocator, + const bool isInternal = false) { - if(!isInternal && parseInfo->languageAccent != QXmlQuery::XQuery10) + /* We treat XPath 2.0 as a subset of XSL-T 2.0, so if XPath 2.0 is allowed + * and XSL-T is the language, it's ok. */ + if(!isInternal && + (!allowedLanguages.testFlag(parseInfo->languageAccent) && !(allowedLanguages.testFlag(QXmlQuery::XPath20) && parseInfo->languageAccent == QXmlQuery::XSLT20))) { - parseInfo->staticContext->error(QtXmlPatterns::tr("A construct was encountered which only is allowed in XQuery."), + + QString langName; + + switch(parseInfo->languageAccent) + { + case QXmlQuery::XPath20: + langName = QLatin1String("XPath 2.0"); + break; + case QXmlQuery::XSLT20: + langName = QLatin1String("XSL-T 2.0"); + break; + case QXmlQuery::XQuery10: + langName = QLatin1String("XQuery 1.0"); + break; + case QXmlQuery::XmlSchema11IdentityConstraintSelector: + langName = QtXmlPatterns::tr("W3C XML Schema identity constraint selector"); + break; + case QXmlQuery::XmlSchema11IdentityConstraintField: + langName = QtXmlPatterns::tr("W3C XML Schema identity constraint field"); + break; + } + + parseInfo->staticContext->error(QtXmlPatterns::tr("A construct was encountered " + "which is disallowed in the current language(%1).").arg(langName), ReportContext::XPST0003, fromYYLTYPE(sourceLocator, parseInfo)); @@ -1366,7 +1400,7 @@ typedef struct YYLTYPE /* Copy the second part of user declarations. */ /* Line 221 of yacc.c. */ -#line 1289 "qquerytransformparser.cpp" +#line 1323 "qquerytransformparser.cpp" #ifdef short # undef short @@ -1850,54 +1884,54 @@ static const yytype_int16 yyrhs[] = /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 1341, 1341, 1342, 1344, 1345, 1376, 1377, 1393, 1491, - 1493, 1499, 1501, 1508, 1514, 1520, 1527, 1530, 1534, 1538, - 1558, 1572, 1576, 1570, 1639, 1643, 1660, 1663, 1665, 1670, - 1671, 1675, 1676, 1680, 1684, 1688, 1690, 1691, 1693, 1695, - 1741, 1755, 1760, 1765, 1766, 1768, 1783, 1798, 1808, 1823, - 1827, 1832, 1846, 1850, 1855, 1869, 1874, 1879, 1884, 1889, - 1905, 1928, 1936, 1937, 1938, 1940, 1957, 1958, 1960, 1961, - 1963, 1964, 1966, 2021, 2025, 2031, 2034, 2039, 2053, 2057, - 2063, 2062, 2171, 2174, 2180, 2201, 2207, 2211, 2213, 2218, - 2228, 2229, 2234, 2235, 2244, 2314, 2325, 2326, 2330, 2335, - 2404, 2405, 2409, 2414, 2458, 2459, 2464, 2471, 2477, 2478, - 2479, 2480, 2481, 2482, 2488, 2493, 2499, 2502, 2507, 2513, - 2519, 2523, 2548, 2549, 2553, 2557, 2551, 2598, 2601, 2596, - 2617, 2618, 2619, 2622, 2626, 2634, 2633, 2647, 2646, 2655, - 2656, 2657, 2659, 2667, 2678, 2681, 2683, 2688, 2695, 2702, - 2708, 2728, 2733, 2739, 2742, 2744, 2745, 2752, 2758, 2762, - 2767, 2768, 2771, 2775, 2770, 2784, 2788, 2783, 2796, 2799, - 2803, 2798, 2812, 2816, 2811, 2824, 2826, 2854, 2853, 2865, - 2873, 2864, 2884, 2885, 2888, 2892, 2897, 2902, 2901, 2917, - 2922, 2923, 2928, 2929, 2934, 2935, 2936, 2937, 2939, 2940, - 2945, 2946, 2951, 2952, 2954, 2955, 2960, 2961, 2962, 2963, - 2965, 2966, 2971, 2972, 2977, 2978, 2980, 2984, 2989, 2990, - 2996, 2997, 3002, 3003, 3008, 3009, 3014, 3015, 3020, 3024, - 3029, 3030, 3031, 3033, 3038, 3039, 3040, 3041, 3042, 3043, - 3045, 3050, 3051, 3052, 3053, 3054, 3055, 3057, 3062, 3063, - 3064, 3066, 3080, 3081, 3082, 3084, 3100, 3104, 3109, 3110, - 3112, 3117, 3118, 3120, 3126, 3130, 3136, 3139, 3140, 3144, - 3153, 3158, 3162, 3163, 3168, 3167, 3182, 3189, 3188, 3203, - 3211, 3211, 3220, 3222, 3225, 3230, 3232, 3236, 3302, 3305, - 3311, 3314, 3323, 3327, 3331, 3336, 3337, 3342, 3343, 3346, - 3345, 3375, 3377, 3378, 3380, 3394, 3395, 3396, 3397, 3398, - 3399, 3400, 3401, 3402, 3403, 3404, 3405, 3408, 3407, 3417, - 3428, 3433, 3435, 3440, 3441, 3443, 3447, 3449, 3453, 3462, - 3468, 3469, 3474, 3475, 3476, 3477, 3478, 3479, 3480, 3481, - 3491, 3492, 3497, 3501, 3506, 3511, 3516, 3521, 3525, 3530, - 3535, 3540, 3569, 3573, 3580, 3582, 3586, 3588, 3589, 3590, - 3624, 3633, 3622, 3874, 3878, 3898, 3901, 3907, 3912, 3917, - 3923, 3926, 3936, 3943, 3947, 3953, 3967, 3973, 3990, 3995, - 4008, 4009, 4010, 4011, 4012, 4013, 4014, 4016, 4024, 4023, - 4063, 4066, 4071, 4086, 4091, 4098, 4110, 4114, 4110, 4120, - 4122, 4126, 4128, 4143, 4147, 4156, 4161, 4165, 4171, 4174, - 4179, 4184, 4189, 4190, 4191, 4192, 4194, 4195, 4196, 4197, - 4202, 4238, 4239, 4240, 4241, 4242, 4243, 4244, 4246, 4251, - 4256, 4262, 4263, 4265, 4270, 4275, 4280, 4285, 4301, 4302, - 4304, 4309, 4314, 4318, 4330, 4343, 4353, 4358, 4363, 4368, - 4382, 4396, 4397, 4399, 4409, 4411, 4416, 4423, 4430, 4432, - 4434, 4435, 4437, 4441, 4446, 4447, 4449, 4455, 4457, 4459, - 4460, 4462, 4474 + 0, 1375, 1375, 1376, 1378, 1379, 1410, 1411, 1427, 1525, + 1527, 1533, 1535, 1542, 1548, 1554, 1561, 1564, 1568, 1572, + 1592, 1606, 1610, 1604, 1673, 1677, 1694, 1697, 1699, 1704, + 1705, 1709, 1710, 1714, 1718, 1722, 1724, 1725, 1727, 1729, + 1775, 1789, 1794, 1799, 1800, 1802, 1817, 1832, 1842, 1857, + 1861, 1866, 1880, 1884, 1889, 1903, 1908, 1913, 1918, 1923, + 1939, 1962, 1970, 1971, 1972, 1974, 1991, 1992, 1994, 1995, + 1997, 1998, 2000, 2055, 2059, 2065, 2068, 2073, 2087, 2091, + 2097, 2096, 2205, 2208, 2214, 2235, 2241, 2245, 2247, 2252, + 2262, 2263, 2268, 2269, 2278, 2348, 2359, 2360, 2364, 2369, + 2438, 2439, 2443, 2448, 2492, 2493, 2498, 2505, 2511, 2512, + 2513, 2514, 2515, 2516, 2522, 2527, 2533, 2536, 2541, 2547, + 2553, 2557, 2582, 2583, 2587, 2591, 2585, 2632, 2635, 2630, + 2651, 2652, 2653, 2656, 2660, 2668, 2667, 2681, 2680, 2689, + 2690, 2691, 2693, 2701, 2712, 2715, 2717, 2722, 2729, 2736, + 2742, 2762, 2767, 2773, 2776, 2778, 2779, 2786, 2792, 2796, + 2801, 2802, 2805, 2809, 2804, 2819, 2823, 2818, 2831, 2834, + 2838, 2833, 2848, 2852, 2847, 2860, 2862, 2890, 2889, 2901, + 2909, 2900, 2920, 2921, 2924, 2928, 2933, 2938, 2937, 2953, + 2959, 2960, 2966, 2967, 2973, 2974, 2975, 2976, 2978, 2979, + 2985, 2986, 2992, 2993, 2995, 2996, 3002, 3003, 3004, 3005, + 3007, 3008, 3018, 3019, 3025, 3026, 3028, 3032, 3037, 3038, + 3045, 3046, 3052, 3053, 3059, 3060, 3066, 3067, 3073, 3077, + 3082, 3083, 3084, 3086, 3092, 3093, 3094, 3095, 3096, 3097, + 3099, 3104, 3105, 3106, 3107, 3108, 3109, 3111, 3116, 3117, + 3118, 3120, 3134, 3135, 3136, 3138, 3155, 3159, 3164, 3165, + 3167, 3172, 3173, 3175, 3181, 3185, 3191, 3194, 3195, 3199, + 3208, 3213, 3217, 3218, 3223, 3222, 3237, 3245, 3244, 3260, + 3268, 3268, 3277, 3279, 3282, 3287, 3289, 3293, 3359, 3362, + 3368, 3371, 3380, 3384, 3388, 3393, 3394, 3399, 3400, 3403, + 3402, 3432, 3434, 3435, 3437, 3481, 3482, 3483, 3484, 3485, + 3486, 3487, 3488, 3489, 3490, 3491, 3492, 3495, 3494, 3505, + 3516, 3521, 3523, 3528, 3529, 3534, 3538, 3540, 3544, 3553, + 3560, 3561, 3567, 3568, 3569, 3570, 3571, 3572, 3573, 3574, + 3584, 3585, 3590, 3595, 3601, 3607, 3612, 3617, 3622, 3628, + 3633, 3638, 3668, 3672, 3679, 3681, 3685, 3690, 3691, 3692, + 3726, 3735, 3724, 3976, 3980, 4000, 4003, 4009, 4014, 4019, + 4025, 4028, 4038, 4045, 4049, 4055, 4069, 4075, 4092, 4097, + 4110, 4111, 4112, 4113, 4114, 4115, 4116, 4118, 4126, 4125, + 4165, 4168, 4173, 4188, 4193, 4200, 4212, 4216, 4212, 4222, + 4224, 4228, 4230, 4245, 4249, 4258, 4263, 4267, 4273, 4276, + 4281, 4286, 4291, 4292, 4293, 4294, 4296, 4297, 4298, 4299, + 4304, 4340, 4341, 4342, 4343, 4344, 4345, 4346, 4348, 4353, + 4358, 4364, 4365, 4367, 4372, 4377, 4382, 4387, 4403, 4404, + 4406, 4411, 4416, 4420, 4432, 4445, 4455, 4460, 4465, 4470, + 4484, 4498, 4499, 4501, 4511, 4513, 4518, 4525, 4532, 4534, + 4536, 4537, 4539, 4543, 4548, 4549, 4551, 4557, 4559, 4561, + 4565, 4570, 4582 }; #endif @@ -3726,7 +3760,7 @@ yyreduce: { case 5: /* Line 1269 of yacc.c. */ -#line 1346 "querytransformparser.ypp" +#line 1380 "querytransformparser.ypp" { /* Suppress more compiler warnings about unused defines. */ @@ -3760,7 +3794,7 @@ yyreduce: case 7: /* Line 1269 of yacc.c. */ -#line 1378 "querytransformparser.ypp" +#line 1412 "querytransformparser.ypp" { const QRegExp encNameRegExp(QLatin1String("[A-Za-z][A-Za-z0-9._\\-]*")); @@ -3779,7 +3813,7 @@ yyreduce: case 8: /* Line 1269 of yacc.c. */ -#line 1394 "querytransformparser.ypp" +#line 1428 "querytransformparser.ypp" { /* In XSL-T, we can have dangling variable references, so resolve them * before we proceed with other steps, such as checking circularity. */ @@ -3880,7 +3914,7 @@ yyreduce: case 10: /* Line 1269 of yacc.c. */ -#line 1494 "querytransformparser.ypp" +#line 1528 "querytransformparser.ypp" { // TODO add to namespace context parseInfo->moduleNamespace = parseInfo->staticContext->namePool()->allocateNamespace((yyvsp[(3) - (6)].sval)); @@ -3889,9 +3923,9 @@ yyreduce: case 12: /* Line 1269 of yacc.c. */ -#line 1502 "querytransformparser.ypp" +#line 1536 "querytransformparser.ypp" { - disallowedConstruct(parseInfo, (yyloc)); + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc)); if(parseInfo->hasSecondPrologPart) parseInfo->staticContext->error(QtXmlPatterns::tr("A default namespace declaration must occur before function, " "variable, and option declarations."), ReportContext::XPST0003, fromYYLTYPE((yyloc), parseInfo)); @@ -3900,7 +3934,7 @@ yyreduce: case 13: /* Line 1269 of yacc.c. */ -#line 1509 "querytransformparser.ypp" +#line 1543 "querytransformparser.ypp" { if(parseInfo->hasSecondPrologPart) parseInfo->staticContext->error(QtXmlPatterns::tr("A default namespace declaration must occur before function, " @@ -3910,7 +3944,7 @@ yyreduce: case 14: /* Line 1269 of yacc.c. */ -#line 1515 "querytransformparser.ypp" +#line 1549 "querytransformparser.ypp" { if(parseInfo->hasSecondPrologPart) parseInfo->staticContext->error(QtXmlPatterns::tr("Namespace declarations must occur before function, " @@ -3920,9 +3954,9 @@ yyreduce: case 15: /* Line 1269 of yacc.c. */ -#line 1521 "querytransformparser.ypp" +#line 1555 "querytransformparser.ypp" { - disallowedConstruct(parseInfo, (yyloc)); + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc)); if(parseInfo->hasSecondPrologPart) parseInfo->staticContext->error(QtXmlPatterns::tr("Module imports must occur before function, " "variable, and option declarations."), ReportContext::XPST0003, fromYYLTYPE((yyloc), parseInfo)); @@ -3931,7 +3965,7 @@ yyreduce: case 17: /* Line 1269 of yacc.c. */ -#line 1531 "querytransformparser.ypp" +#line 1565 "querytransformparser.ypp" { parseInfo->hasSecondPrologPart = true; } @@ -3939,7 +3973,7 @@ yyreduce: case 18: /* Line 1269 of yacc.c. */ -#line 1535 "querytransformparser.ypp" +#line 1569 "querytransformparser.ypp" { parseInfo->hasSecondPrologPart = true; } @@ -3947,16 +3981,16 @@ yyreduce: case 19: /* Line 1269 of yacc.c. */ -#line 1539 "querytransformparser.ypp" +#line 1573 "querytransformparser.ypp" { - disallowedConstruct(parseInfo, (yyloc)); + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc)); parseInfo->hasSecondPrologPart = true; } break; case 20: /* Line 1269 of yacc.c. */ -#line 1562 "querytransformparser.ypp" +#line 1596 "querytransformparser.ypp" { Template::Ptr temp(create(new Template(parseInfo->currentImportPrecedence, (yyvsp[(5) - (7)].sequenceType)), (yyloc), parseInfo)); @@ -3969,7 +4003,7 @@ yyreduce: case 21: /* Line 1269 of yacc.c. */ -#line 1572 "querytransformparser.ypp" +#line 1606 "querytransformparser.ypp" { parseInfo->isParsingPattern = true; } @@ -3977,7 +4011,7 @@ yyreduce: case 22: /* Line 1269 of yacc.c. */ -#line 1576 "querytransformparser.ypp" +#line 1610 "querytransformparser.ypp" { parseInfo->isParsingPattern = false; } @@ -3985,7 +4019,7 @@ yyreduce: case 23: /* Line 1269 of yacc.c. */ -#line 1585 "querytransformparser.ypp" +#line 1619 "querytransformparser.ypp" { /* In this grammar branch, we're guaranteed to be a template rule, but * may also be a named template. */ @@ -4042,7 +4076,7 @@ yyreduce: case 24: /* Line 1269 of yacc.c. */ -#line 1639 "querytransformparser.ypp" +#line 1673 "querytransformparser.ypp" { (yyval.enums.Double) = std::numeric_limits::quiet_NaN(); } @@ -4050,7 +4084,7 @@ yyreduce: case 25: /* Line 1269 of yacc.c. */ -#line 1644 "querytransformparser.ypp" +#line 1678 "querytransformparser.ypp" { const AtomicValue::Ptr val(Decimal::fromLexical((yyvsp[(2) - (2)].sval))); if(val->hasError()) @@ -4069,7 +4103,7 @@ yyreduce: case 26: /* Line 1269 of yacc.c. */ -#line 1660 "querytransformparser.ypp" +#line 1694 "querytransformparser.ypp" { (yyval.qName) = QXmlName(); } @@ -4077,7 +4111,7 @@ yyreduce: case 28: /* Line 1269 of yacc.c. */ -#line 1666 "querytransformparser.ypp" +#line 1700 "querytransformparser.ypp" { (yyval.qName) = (yyvsp[(2) - (2)].qName); } @@ -4085,42 +4119,42 @@ yyreduce: case 30: /* Line 1269 of yacc.c. */ -#line 1672 "querytransformparser.ypp" +#line 1706 "querytransformparser.ypp" { - disallowedConstruct(parseInfo, (yyloc)); + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc)); } break; case 32: /* Line 1269 of yacc.c. */ -#line 1677 "querytransformparser.ypp" +#line 1711 "querytransformparser.ypp" { - disallowedConstruct(parseInfo, (yyloc)); + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc)); } break; case 33: /* Line 1269 of yacc.c. */ -#line 1681 "querytransformparser.ypp" +#line 1715 "querytransformparser.ypp" { - disallowedConstruct(parseInfo, (yyloc)); + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc)); } break; case 34: /* Line 1269 of yacc.c. */ -#line 1685 "querytransformparser.ypp" +#line 1719 "querytransformparser.ypp" { - disallowedConstruct(parseInfo, (yyloc)); + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc)); } break; case 39: /* Line 1269 of yacc.c. */ -#line 1696 "querytransformparser.ypp" +#line 1730 "querytransformparser.ypp" { if(!(yyvsp[(6) - (7)].enums.Bool)) - disallowedConstruct(parseInfo, (yyloc)); + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc)); if((yyvsp[(3) - (7)].sval) == QLatin1String("xmlns")) { @@ -4166,7 +4200,7 @@ yyreduce: case 40: /* Line 1269 of yacc.c. */ -#line 1742 "querytransformparser.ypp" +#line 1776 "querytransformparser.ypp" { if(parseInfo->hasDeclaration(ParserContext::BoundarySpaceDecl)) { @@ -4183,7 +4217,7 @@ yyreduce: case 41: /* Line 1269 of yacc.c. */ -#line 1756 "querytransformparser.ypp" +#line 1790 "querytransformparser.ypp" { (yyval.enums.boundarySpacePolicy) = StaticContext::BSPStrip; } @@ -4191,7 +4225,7 @@ yyreduce: case 42: /* Line 1269 of yacc.c. */ -#line 1761 "querytransformparser.ypp" +#line 1795 "querytransformparser.ypp" { (yyval.enums.boundarySpacePolicy) = StaticContext::BSPPreserve; } @@ -4199,7 +4233,7 @@ yyreduce: case 45: /* Line 1269 of yacc.c. */ -#line 1770 "querytransformparser.ypp" +#line 1804 "querytransformparser.ypp" { if(parseInfo->hasDeclaration(ParserContext::DeclareDefaultElementNamespace)) { @@ -4216,7 +4250,7 @@ yyreduce: case 46: /* Line 1269 of yacc.c. */ -#line 1785 "querytransformparser.ypp" +#line 1819 "querytransformparser.ypp" { if(parseInfo->hasDeclaration(ParserContext::DeclareDefaultFunctionNamespace)) { @@ -4233,7 +4267,7 @@ yyreduce: case 47: /* Line 1269 of yacc.c. */ -#line 1799 "querytransformparser.ypp" +#line 1833 "querytransformparser.ypp" { if((yyvsp[(3) - (5)].qName).prefix() == StandardPrefixes::empty) { @@ -4246,9 +4280,9 @@ yyreduce: case 48: /* Line 1269 of yacc.c. */ -#line 1809 "querytransformparser.ypp" +#line 1843 "querytransformparser.ypp" { - disallowedConstruct(parseInfo, (yyloc)); + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc)); if(parseInfo->hasDeclaration(ParserContext::OrderingModeDecl)) { parseInfo->staticContext->error(prologMessage("declare ordering"), @@ -4264,7 +4298,7 @@ yyreduce: case 49: /* Line 1269 of yacc.c. */ -#line 1824 "querytransformparser.ypp" +#line 1858 "querytransformparser.ypp" { (yyval.enums.orderingMode) = StaticContext::Ordered; } @@ -4272,7 +4306,7 @@ yyreduce: case 50: /* Line 1269 of yacc.c. */ -#line 1828 "querytransformparser.ypp" +#line 1862 "querytransformparser.ypp" { (yyval.enums.orderingMode) = StaticContext::Unordered; } @@ -4280,7 +4314,7 @@ yyreduce: case 51: /* Line 1269 of yacc.c. */ -#line 1833 "querytransformparser.ypp" +#line 1867 "querytransformparser.ypp" { if(parseInfo->hasDeclaration(ParserContext::EmptyOrderDecl)) { @@ -4297,7 +4331,7 @@ yyreduce: case 52: /* Line 1269 of yacc.c. */ -#line 1847 "querytransformparser.ypp" +#line 1881 "querytransformparser.ypp" { (yyval.enums.orderingEmptySequence) = StaticContext::Least; } @@ -4305,7 +4339,7 @@ yyreduce: case 53: /* Line 1269 of yacc.c. */ -#line 1851 "querytransformparser.ypp" +#line 1885 "querytransformparser.ypp" { (yyval.enums.orderingEmptySequence) = StaticContext::Greatest; } @@ -4313,7 +4347,7 @@ yyreduce: case 54: /* Line 1269 of yacc.c. */ -#line 1857 "querytransformparser.ypp" +#line 1891 "querytransformparser.ypp" { if(parseInfo->hasDeclaration(ParserContext::CopyNamespacesDecl)) { @@ -4329,7 +4363,7 @@ yyreduce: case 55: /* Line 1269 of yacc.c. */ -#line 1870 "querytransformparser.ypp" +#line 1904 "querytransformparser.ypp" { parseInfo->preserveNamespacesMode = true; } @@ -4337,7 +4371,7 @@ yyreduce: case 56: /* Line 1269 of yacc.c. */ -#line 1875 "querytransformparser.ypp" +#line 1909 "querytransformparser.ypp" { parseInfo->preserveNamespacesMode = false; } @@ -4345,7 +4379,7 @@ yyreduce: case 57: /* Line 1269 of yacc.c. */ -#line 1880 "querytransformparser.ypp" +#line 1914 "querytransformparser.ypp" { parseInfo->inheritNamespacesMode = true; } @@ -4353,7 +4387,7 @@ yyreduce: case 58: /* Line 1269 of yacc.c. */ -#line 1885 "querytransformparser.ypp" +#line 1919 "querytransformparser.ypp" { parseInfo->inheritNamespacesMode = false; } @@ -4361,7 +4395,7 @@ yyreduce: case 59: /* Line 1269 of yacc.c. */ -#line 1890 "querytransformparser.ypp" +#line 1924 "querytransformparser.ypp" { if(parseInfo->hasDeclaration(ParserContext::DefaultCollationDecl)) { @@ -4380,9 +4414,9 @@ yyreduce: case 60: /* Line 1269 of yacc.c. */ -#line 1906 "querytransformparser.ypp" +#line 1940 "querytransformparser.ypp" { - disallowedConstruct(parseInfo, (yyloc), (yyvsp[(3) - (5)].enums.Bool)); + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XSLT20), parseInfo, (yyloc), (yyvsp[(3) - (5)].enums.Bool)); if(parseInfo->hasDeclaration(ParserContext::BaseURIDecl)) { parseInfo->staticContext->error(prologMessage("declare base-uri"), @@ -4406,7 +4440,7 @@ yyreduce: case 61: /* Line 1269 of yacc.c. */ -#line 1929 "querytransformparser.ypp" +#line 1963 "querytransformparser.ypp" { parseInfo->staticContext->error(QtXmlPatterns::tr("The Schema Import feature is not supported, " "and therefore %1 declarations cannot occur.") @@ -4417,7 +4451,7 @@ yyreduce: case 65: /* Line 1269 of yacc.c. */ -#line 1941 "querytransformparser.ypp" +#line 1975 "querytransformparser.ypp" { if((yyvsp[(4) - (6)].sval).isEmpty()) { @@ -4437,9 +4471,9 @@ yyreduce: case 72: /* Line 1269 of yacc.c. */ -#line 1968 "querytransformparser.ypp" +#line 2002 "querytransformparser.ypp" { - disallowedConstruct(parseInfo, (yyloc), (yyvsp[(3) - (9)].enums.Bool)); + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc), (yyvsp[(3) - (9)].enums.Bool)); if(variableByName((yyvsp[(5) - (9)].qName), parseInfo)) { parseInfo->staticContext->error(QtXmlPatterns::tr("A variable by name %1 has already " @@ -4494,7 +4528,7 @@ yyreduce: case 73: /* Line 1269 of yacc.c. */ -#line 2022 "querytransformparser.ypp" +#line 2056 "querytransformparser.ypp" { (yyval.expr).reset(); } @@ -4502,7 +4536,7 @@ yyreduce: case 74: /* Line 1269 of yacc.c. */ -#line 2026 "querytransformparser.ypp" +#line 2060 "querytransformparser.ypp" { (yyval.expr) = (yyvsp[(2) - (2)].expr); } @@ -4510,7 +4544,7 @@ yyreduce: case 75: /* Line 1269 of yacc.c. */ -#line 2031 "querytransformparser.ypp" +#line 2065 "querytransformparser.ypp" { (yyval.expr).reset(); } @@ -4518,7 +4552,7 @@ yyreduce: case 76: /* Line 1269 of yacc.c. */ -#line 2035 "querytransformparser.ypp" +#line 2069 "querytransformparser.ypp" { (yyval.expr) = (yyvsp[(2) - (2)].expr); } @@ -4526,7 +4560,7 @@ yyreduce: case 77: /* Line 1269 of yacc.c. */ -#line 2040 "querytransformparser.ypp" +#line 2074 "querytransformparser.ypp" { if(parseInfo->hasDeclaration(ParserContext::ConstructionDecl)) { @@ -4543,7 +4577,7 @@ yyreduce: case 78: /* Line 1269 of yacc.c. */ -#line 2054 "querytransformparser.ypp" +#line 2088 "querytransformparser.ypp" { (yyval.enums.constructionMode) = StaticContext::CMStrip; } @@ -4551,7 +4585,7 @@ yyreduce: case 79: /* Line 1269 of yacc.c. */ -#line 2058 "querytransformparser.ypp" +#line 2092 "querytransformparser.ypp" { (yyval.enums.constructionMode) = StaticContext::CMPreserve; } @@ -4559,7 +4593,7 @@ yyreduce: case 80: /* Line 1269 of yacc.c. */ -#line 2063 "querytransformparser.ypp" +#line 2097 "querytransformparser.ypp" { (yyval.enums.slot) = parseInfo->currentExpressionSlot() - (yyvsp[(6) - (7)].functionArguments).count(); } @@ -4567,10 +4601,10 @@ yyreduce: case 81: /* Line 1269 of yacc.c. */ -#line 2067 "querytransformparser.ypp" +#line 2101 "querytransformparser.ypp" { if(!(yyvsp[(3) - (11)].enums.Bool)) - disallowedConstruct(parseInfo, (yyloc), (yyvsp[(3) - (11)].enums.Bool)); + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc), (yyvsp[(3) - (11)].enums.Bool)); /* If FunctionBody is null, it is 'external', otherwise the value is the body. */ const QXmlName::NamespaceCode ns((yyvsp[(4) - (11)].qName).namespaceURI()); @@ -4674,7 +4708,7 @@ yyreduce: case 82: /* Line 1269 of yacc.c. */ -#line 2171 "querytransformparser.ypp" +#line 2205 "querytransformparser.ypp" { (yyval.functionArguments) = FunctionArgument::List(); } @@ -4682,7 +4716,7 @@ yyreduce: case 83: /* Line 1269 of yacc.c. */ -#line 2175 "querytransformparser.ypp" +#line 2209 "querytransformparser.ypp" { FunctionArgument::List l; l.append((yyvsp[(1) - (1)].functionArgument)); @@ -4692,7 +4726,7 @@ yyreduce: case 84: /* Line 1269 of yacc.c. */ -#line 2181 "querytransformparser.ypp" +#line 2215 "querytransformparser.ypp" { FunctionArgument::List::const_iterator it((yyvsp[(1) - (3)].functionArguments).constBegin()); const FunctionArgument::List::const_iterator end((yyvsp[(1) - (3)].functionArguments).constEnd()); @@ -4716,7 +4750,7 @@ yyreduce: case 85: /* Line 1269 of yacc.c. */ -#line 2202 "querytransformparser.ypp" +#line 2236 "querytransformparser.ypp" { pushVariable((yyvsp[(2) - (3)].qName), (yyvsp[(3) - (3)].sequenceType), Expression::Ptr(), VariableDeclaration::FunctionArgument, (yyloc), parseInfo); (yyval.functionArgument) = FunctionArgument::Ptr(new FunctionArgument((yyvsp[(2) - (3)].qName), (yyvsp[(3) - (3)].sequenceType))); @@ -4725,7 +4759,7 @@ yyreduce: case 86: /* Line 1269 of yacc.c. */ -#line 2208 "querytransformparser.ypp" +#line 2242 "querytransformparser.ypp" { (yyval.expr).reset(); } @@ -4733,7 +4767,7 @@ yyreduce: case 88: /* Line 1269 of yacc.c. */ -#line 2214 "querytransformparser.ypp" +#line 2248 "querytransformparser.ypp" { (yyval.expr) = (yyvsp[(2) - (3)].expr); } @@ -4741,7 +4775,7 @@ yyreduce: case 91: /* Line 1269 of yacc.c. */ -#line 2230 "querytransformparser.ypp" +#line 2264 "querytransformparser.ypp" { (yyval.expr) = create(new CombineNodes((yyvsp[(1) - (3)].expr), CombineNodes::Union, (yyvsp[(3) - (3)].expr)), (yyloc), parseInfo); } @@ -4749,7 +4783,7 @@ yyreduce: case 93: /* Line 1269 of yacc.c. */ -#line 2236 "querytransformparser.ypp" +#line 2270 "querytransformparser.ypp" { /* We write this into a node test. The spec says, 5.5.3 The Meaning of a Pattern: * "Similarly, / matches a document node, and only a document node, @@ -4762,7 +4796,7 @@ yyreduce: case 94: /* Line 1269 of yacc.c. */ -#line 2245 "querytransformparser.ypp" +#line 2279 "querytransformparser.ypp" { /* /axis::node-test * => @@ -4836,7 +4870,7 @@ yyreduce: case 95: /* Line 1269 of yacc.c. */ -#line 2315 "querytransformparser.ypp" +#line 2349 "querytransformparser.ypp" { /* //axis::node-test * => @@ -4851,7 +4885,7 @@ yyreduce: case 97: /* Line 1269 of yacc.c. */ -#line 2327 "querytransformparser.ypp" +#line 2361 "querytransformparser.ypp" { createIdPatternPath((yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr), QXmlNodeModelIndex::AxisParent, (yylsp[(2) - (3)]), parseInfo); } @@ -4859,7 +4893,7 @@ yyreduce: case 98: /* Line 1269 of yacc.c. */ -#line 2331 "querytransformparser.ypp" +#line 2365 "querytransformparser.ypp" { createIdPatternPath((yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr), QXmlNodeModelIndex::AxisAncestor, (yylsp[(2) - (3)]), parseInfo); } @@ -4867,7 +4901,7 @@ yyreduce: case 99: /* Line 1269 of yacc.c. */ -#line 2336 "querytransformparser.ypp" +#line 2370 "querytransformparser.ypp" { const Expression::List ands((yyvsp[(1) - (1)].expr)->operands()); const FunctionSignature::Ptr signature((yyvsp[(1) - (1)].expr)->as()->signature()); @@ -4939,7 +4973,7 @@ yyreduce: case 101: /* Line 1269 of yacc.c. */ -#line 2406 "querytransformparser.ypp" +#line 2440 "querytransformparser.ypp" { (yyval.expr) = createPatternPath((yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr), QXmlNodeModelIndex::AxisParent, (yylsp[(2) - (3)]), parseInfo); } @@ -4947,7 +4981,7 @@ yyreduce: case 102: /* Line 1269 of yacc.c. */ -#line 2410 "querytransformparser.ypp" +#line 2444 "querytransformparser.ypp" { (yyval.expr) = createPatternPath((yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr), QXmlNodeModelIndex::AxisAncestor, (yylsp[(2) - (3)]), parseInfo); } @@ -4955,7 +4989,7 @@ yyreduce: case 103: /* Line 1269 of yacc.c. */ -#line 2415 "querytransformparser.ypp" +#line 2449 "querytransformparser.ypp" { const Expression::Ptr expr(findAxisStep((yyvsp[(1) - (1)].expr))); @@ -5002,7 +5036,7 @@ yyreduce: case 105: /* Line 1269 of yacc.c. */ -#line 2460 "querytransformparser.ypp" +#line 2494 "querytransformparser.ypp" { (yyval.expr) = create(new ExpressionSequence((yyvsp[(1) - (1)].expressionList)), (yyloc), parseInfo); } @@ -5010,7 +5044,7 @@ yyreduce: case 106: /* Line 1269 of yacc.c. */ -#line 2465 "querytransformparser.ypp" +#line 2499 "querytransformparser.ypp" { Expression::List l; l.append((yyvsp[(1) - (3)].expr)); @@ -5021,7 +5055,7 @@ yyreduce: case 107: /* Line 1269 of yacc.c. */ -#line 2472 "querytransformparser.ypp" +#line 2506 "querytransformparser.ypp" { (yyvsp[(1) - (3)].expressionList).append((yyvsp[(3) - (3)].expr)); (yyval.expressionList) = (yyvsp[(1) - (3)].expressionList); @@ -5030,7 +5064,7 @@ yyreduce: case 113: /* Line 1269 of yacc.c. */ -#line 2483 "querytransformparser.ypp" +#line 2517 "querytransformparser.ypp" { (yyval.expr) = createDirAttributeValue((yyvsp[(3) - (4)].expressionList), parseInfo, (yyloc)); } @@ -5038,7 +5072,7 @@ yyreduce: case 114: /* Line 1269 of yacc.c. */ -#line 2488 "querytransformparser.ypp" +#line 2522 "querytransformparser.ypp" { QVector result; result.append(QXmlName(StandardNamespaces::InternalXSLT, StandardLocalNames::Default)); @@ -5048,7 +5082,7 @@ yyreduce: case 115: /* Line 1269 of yacc.c. */ -#line 2494 "querytransformparser.ypp" +#line 2528 "querytransformparser.ypp" { (yyval.qNameVector) = (yyvsp[(2) - (2)].qNameVector); } @@ -5056,7 +5090,7 @@ yyreduce: case 116: /* Line 1269 of yacc.c. */ -#line 2499 "querytransformparser.ypp" +#line 2533 "querytransformparser.ypp" { (yyval.qName) = QXmlName(StandardNamespaces::InternalXSLT, StandardLocalNames::Default); } @@ -5064,7 +5098,7 @@ yyreduce: case 117: /* Line 1269 of yacc.c. */ -#line 2503 "querytransformparser.ypp" +#line 2537 "querytransformparser.ypp" { (yyval.qName) = (yyvsp[(2) - (2)].qName); } @@ -5072,7 +5106,7 @@ yyreduce: case 118: /* Line 1269 of yacc.c. */ -#line 2508 "querytransformparser.ypp" +#line 2542 "querytransformparser.ypp" { QVector result; result.append((yyvsp[(1) - (1)].qName)); @@ -5082,7 +5116,7 @@ yyreduce: case 119: /* Line 1269 of yacc.c. */ -#line 2514 "querytransformparser.ypp" +#line 2548 "querytransformparser.ypp" { (yyvsp[(1) - (3)].qNameVector).append((yyvsp[(3) - (3)].qName)); (yyval.qNameVector) = (yyvsp[(1) - (3)].qNameVector); @@ -5091,7 +5125,7 @@ yyreduce: case 120: /* Line 1269 of yacc.c. */ -#line 2520 "querytransformparser.ypp" +#line 2554 "querytransformparser.ypp" { (yyval.qName) = (yyvsp[(1) - (1)].qName); } @@ -5099,7 +5133,7 @@ yyreduce: case 121: /* Line 1269 of yacc.c. */ -#line 2524 "querytransformparser.ypp" +#line 2558 "querytransformparser.ypp" { if((yyvsp[(1) - (1)].sval) == QLatin1String("#current")) (yyval.qName) = QXmlName(StandardNamespaces::InternalXSLT, StandardLocalNames::current); @@ -5126,7 +5160,7 @@ yyreduce: case 124: /* Line 1269 of yacc.c. */ -#line 2553 "querytransformparser.ypp" +#line 2587 "querytransformparser.ypp" { /* We're pushing the range variable here, not the positional. */ (yyval.expr) = pushVariable((yyvsp[(3) - (7)].qName), quantificationType((yyvsp[(4) - (7)].sequenceType)), (yyvsp[(7) - (7)].expr), VariableDeclaration::RangeVariable, (yyloc), parseInfo); @@ -5135,7 +5169,7 @@ yyreduce: case 125: /* Line 1269 of yacc.c. */ -#line 2557 "querytransformparser.ypp" +#line 2591 "querytransformparser.ypp" { /* It is ok this appears after PositionalVar, because currentRangeSlot() * uses a different "channel" than currentPositionSlot(), so they can't trash @@ -5146,7 +5180,7 @@ yyreduce: case 126: /* Line 1269 of yacc.c. */ -#line 2564 "querytransformparser.ypp" +#line 2598 "querytransformparser.ypp" { Q_ASSERT((yyvsp[(7) - (10)].expr)); Q_ASSERT((yyvsp[(10) - (10)].expr)); @@ -5182,7 +5216,7 @@ yyreduce: case 127: /* Line 1269 of yacc.c. */ -#line 2598 "querytransformparser.ypp" +#line 2632 "querytransformparser.ypp" { pushVariable((yyvsp[(3) - (7)].qName), quantificationType((yyvsp[(4) - (7)].sequenceType)), (yyvsp[(7) - (7)].expr), VariableDeclaration::RangeVariable, (yyloc), parseInfo); } @@ -5190,7 +5224,7 @@ yyreduce: case 128: /* Line 1269 of yacc.c. */ -#line 2601 "querytransformparser.ypp" +#line 2635 "querytransformparser.ypp" { /* It is ok this appears after PositionalVar, because currentRangeSlot() * uses a different "channel" than currentPositionSlot(), so they can't trash @@ -5201,7 +5235,7 @@ yyreduce: case 129: /* Line 1269 of yacc.c. */ -#line 2608 "querytransformparser.ypp" +#line 2642 "querytransformparser.ypp" { (yyval.expr) = create(new ForClause((yyvsp[(9) - (10)].enums.slot), (yyvsp[(7) - (10)].expr), (yyvsp[(10) - (10)].expr), (yyvsp[(5) - (10)].enums.slot)), (yyloc), parseInfo); @@ -5214,7 +5248,7 @@ yyreduce: case 133: /* Line 1269 of yacc.c. */ -#line 2622 "querytransformparser.ypp" +#line 2656 "querytransformparser.ypp" { (yyval.enums.slot) = -1; } @@ -5222,7 +5256,7 @@ yyreduce: case 134: /* Line 1269 of yacc.c. */ -#line 2627 "querytransformparser.ypp" +#line 2661 "querytransformparser.ypp" { pushVariable((yyvsp[(3) - (3)].qName), CommonSequenceTypes::ExactlyOneInteger, Expression::Ptr(), VariableDeclaration::PositionalVariable, (yyloc), parseInfo); @@ -5232,7 +5266,7 @@ yyreduce: case 135: /* Line 1269 of yacc.c. */ -#line 2634 "querytransformparser.ypp" +#line 2668 "querytransformparser.ypp" { (yyval.expr) = pushVariable((yyvsp[(4) - (7)].qName), quantificationType((yyvsp[(5) - (7)].sequenceType)), (yyvsp[(7) - (7)].expr), VariableDeclaration::ExpressionVariable, (yyloc), parseInfo); } @@ -5240,9 +5274,9 @@ yyreduce: case 136: /* Line 1269 of yacc.c. */ -#line 2638 "querytransformparser.ypp" +#line 2672 "querytransformparser.ypp" { - disallowedConstruct(parseInfo, (yyloc), (yyvsp[(2) - (9)].enums.Bool)); + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc), (yyvsp[(2) - (9)].enums.Bool)); Q_ASSERT(parseInfo->variables.top()->name == (yyvsp[(4) - (9)].qName)); (yyval.expr) = create(new LetClause((yyvsp[(8) - (9)].expr), (yyvsp[(9) - (9)].expr), parseInfo->variables.top()), (yyloc), parseInfo); @@ -5252,13 +5286,13 @@ yyreduce: case 137: /* Line 1269 of yacc.c. */ -#line 2647 "querytransformparser.ypp" +#line 2681 "querytransformparser.ypp" { (yyval.expr) = pushVariable((yyvsp[(3) - (6)].qName), quantificationType((yyvsp[(4) - (6)].sequenceType)), (yyvsp[(6) - (6)].expr), VariableDeclaration::ExpressionVariable, (yyloc), parseInfo);} break; case 138: /* Line 1269 of yacc.c. */ -#line 2649 "querytransformparser.ypp" +#line 2683 "querytransformparser.ypp" { Q_ASSERT(parseInfo->variables.top()->name == (yyvsp[(3) - (8)].qName)); (yyval.expr) = create(new LetClause((yyvsp[(7) - (8)].expr), (yyvsp[(8) - (8)].expr), parseInfo->variables.top()), (yyloc), parseInfo); @@ -5268,7 +5302,7 @@ yyreduce: case 142: /* Line 1269 of yacc.c. */ -#line 2660 "querytransformparser.ypp" +#line 2694 "querytransformparser.ypp" { if((yyvsp[(1) - (3)].orderSpecs).isEmpty()) (yyval.expr) = (yyvsp[(3) - (3)].expr); @@ -5279,7 +5313,7 @@ yyreduce: case 143: /* Line 1269 of yacc.c. */ -#line 2668 "querytransformparser.ypp" +#line 2702 "querytransformparser.ypp" { if((yyvsp[(3) - (5)].orderSpecs).isEmpty()) (yyval.expr) = create(new IfThenClause((yyvsp[(2) - (5)].expr), (yyvsp[(5) - (5)].expr), create(new EmptySequence, (yyloc), parseInfo)), (yyloc), parseInfo); @@ -5292,7 +5326,7 @@ yyreduce: case 144: /* Line 1269 of yacc.c. */ -#line 2678 "querytransformparser.ypp" +#line 2712 "querytransformparser.ypp" { (yyval.orderSpecs) = OrderSpecTransfer::List(); } @@ -5300,7 +5334,7 @@ yyreduce: case 146: /* Line 1269 of yacc.c. */ -#line 2684 "querytransformparser.ypp" +#line 2718 "querytransformparser.ypp" { (yyval.orderSpecs) = (yyvsp[(2) - (2)].orderSpecs); } @@ -5308,7 +5342,7 @@ yyreduce: case 147: /* Line 1269 of yacc.c. */ -#line 2689 "querytransformparser.ypp" +#line 2723 "querytransformparser.ypp" { OrderSpecTransfer::List list; list += (yyvsp[(1) - (3)].orderSpecs); @@ -5319,7 +5353,7 @@ yyreduce: case 148: /* Line 1269 of yacc.c. */ -#line 2696 "querytransformparser.ypp" +#line 2730 "querytransformparser.ypp" { OrderSpecTransfer::List list; list.append((yyvsp[(1) - (1)].orderSpec)); @@ -5329,7 +5363,7 @@ yyreduce: case 149: /* Line 1269 of yacc.c. */ -#line 2703 "querytransformparser.ypp" +#line 2737 "querytransformparser.ypp" { (yyval.orderSpec) = OrderSpecTransfer((yyvsp[(1) - (4)].expr), OrderBy::OrderSpec((yyvsp[(2) - (4)].enums.sortDirection), (yyvsp[(3) - (4)].enums.orderingEmptySequence))); } @@ -5337,7 +5371,7 @@ yyreduce: case 150: /* Line 1269 of yacc.c. */ -#line 2708 "querytransformparser.ypp" +#line 2742 "querytransformparser.ypp" { /* Where does the specification state the default value is ascending? * @@ -5361,7 +5395,7 @@ yyreduce: case 151: /* Line 1269 of yacc.c. */ -#line 2729 "querytransformparser.ypp" +#line 2763 "querytransformparser.ypp" { (yyval.enums.sortDirection) = OrderBy::OrderSpec::Ascending; } @@ -5369,7 +5403,7 @@ yyreduce: case 152: /* Line 1269 of yacc.c. */ -#line 2734 "querytransformparser.ypp" +#line 2768 "querytransformparser.ypp" { (yyval.enums.sortDirection) = OrderBy::OrderSpec::Descending; } @@ -5377,7 +5411,7 @@ yyreduce: case 153: /* Line 1269 of yacc.c. */ -#line 2739 "querytransformparser.ypp" +#line 2773 "querytransformparser.ypp" { (yyval.enums.orderingEmptySequence) = parseInfo->staticContext->orderingEmptySequence(); } @@ -5385,7 +5419,7 @@ yyreduce: case 156: /* Line 1269 of yacc.c. */ -#line 2746 "querytransformparser.ypp" +#line 2780 "querytransformparser.ypp" { if(parseInfo->isXSLT()) resolveAndCheckCollation((yyvsp[(2) - (2)].sval), parseInfo, (yyloc)); @@ -5396,7 +5430,7 @@ yyreduce: case 157: /* Line 1269 of yacc.c. */ -#line 2753 "querytransformparser.ypp" +#line 2787 "querytransformparser.ypp" { /* We do nothing. We don't use collations, and we have this non-terminal * in order to accept expressions. */ @@ -5405,7 +5439,7 @@ yyreduce: case 158: /* Line 1269 of yacc.c. */ -#line 2759 "querytransformparser.ypp" +#line 2793 "querytransformparser.ypp" { parseInfo->orderStability.push(OrderBy::StableOrder); } @@ -5413,7 +5447,7 @@ yyreduce: case 159: /* Line 1269 of yacc.c. */ -#line 2763 "querytransformparser.ypp" +#line 2797 "querytransformparser.ypp" { parseInfo->orderStability.push(OrderBy::UnstableOrder); } @@ -5421,7 +5455,7 @@ yyreduce: case 162: /* Line 1269 of yacc.c. */ -#line 2771 "querytransformparser.ypp" +#line 2805 "querytransformparser.ypp" { pushVariable((yyvsp[(3) - (6)].qName), quantificationType((yyvsp[(4) - (6)].sequenceType)), (yyvsp[(6) - (6)].expr), VariableDeclaration::RangeVariable, (yyloc), parseInfo); @@ -5430,14 +5464,15 @@ yyreduce: case 163: /* Line 1269 of yacc.c. */ -#line 2775 "querytransformparser.ypp" +#line 2809 "querytransformparser.ypp" {(yyval.enums.slot) = parseInfo->staticContext->currentRangeSlot();} break; case 164: /* Line 1269 of yacc.c. */ -#line 2777 "querytransformparser.ypp" +#line 2811 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = create(new QuantifiedExpression((yyvsp[(8) - (9)].enums.slot), QuantifiedExpression::Some, (yyvsp[(6) - (9)].expr), (yyvsp[(9) - (9)].expr)), (yyloc), parseInfo); parseInfo->finalizePushedVariable(); @@ -5446,7 +5481,7 @@ yyreduce: case 165: /* Line 1269 of yacc.c. */ -#line 2784 "querytransformparser.ypp" +#line 2819 "querytransformparser.ypp" { (yyval.expr) = pushVariable((yyvsp[(3) - (6)].qName), quantificationType((yyvsp[(4) - (6)].sequenceType)), (yyvsp[(6) - (6)].expr), VariableDeclaration::RangeVariable, (yyloc), parseInfo); @@ -5455,13 +5490,13 @@ yyreduce: case 166: /* Line 1269 of yacc.c. */ -#line 2788 "querytransformparser.ypp" +#line 2823 "querytransformparser.ypp" {(yyval.enums.slot) = parseInfo->staticContext->currentRangeSlot();} break; case 167: /* Line 1269 of yacc.c. */ -#line 2790 "querytransformparser.ypp" +#line 2825 "querytransformparser.ypp" { (yyval.expr) = create(new QuantifiedExpression((yyvsp[(8) - (9)].enums.slot), QuantifiedExpression::Some, (yyvsp[(7) - (9)].expr), (yyvsp[(9) - (9)].expr)), (yyloc), parseInfo); @@ -5471,7 +5506,7 @@ yyreduce: case 169: /* Line 1269 of yacc.c. */ -#line 2799 "querytransformparser.ypp" +#line 2834 "querytransformparser.ypp" { pushVariable((yyvsp[(3) - (6)].qName), quantificationType((yyvsp[(4) - (6)].sequenceType)), (yyvsp[(6) - (6)].expr), VariableDeclaration::RangeVariable, (yyloc), parseInfo); @@ -5480,14 +5515,15 @@ yyreduce: case 170: /* Line 1269 of yacc.c. */ -#line 2803 "querytransformparser.ypp" +#line 2838 "querytransformparser.ypp" {(yyval.enums.slot) = parseInfo->staticContext->currentRangeSlot();} break; case 171: /* Line 1269 of yacc.c. */ -#line 2805 "querytransformparser.ypp" +#line 2840 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = create(new QuantifiedExpression((yyvsp[(8) - (9)].enums.slot), QuantifiedExpression::Every, (yyvsp[(6) - (9)].expr), (yyvsp[(9) - (9)].expr)), (yyloc), parseInfo); parseInfo->finalizePushedVariable(); @@ -5496,7 +5532,7 @@ yyreduce: case 172: /* Line 1269 of yacc.c. */ -#line 2812 "querytransformparser.ypp" +#line 2848 "querytransformparser.ypp" { (yyval.expr) = pushVariable((yyvsp[(3) - (6)].qName), quantificationType((yyvsp[(4) - (6)].sequenceType)), (yyvsp[(6) - (6)].expr), VariableDeclaration::RangeVariable, (yyloc), parseInfo); @@ -5505,13 +5541,13 @@ yyreduce: case 173: /* Line 1269 of yacc.c. */ -#line 2816 "querytransformparser.ypp" +#line 2852 "querytransformparser.ypp" {(yyval.enums.slot) = parseInfo->staticContext->currentRangeSlot();} break; case 174: /* Line 1269 of yacc.c. */ -#line 2818 "querytransformparser.ypp" +#line 2854 "querytransformparser.ypp" { (yyval.expr) = create(new QuantifiedExpression((yyvsp[(8) - (9)].enums.slot), QuantifiedExpression::Every, (yyvsp[(7) - (9)].expr), (yyvsp[(9) - (9)].expr)), (yyloc), parseInfo); @@ -5521,7 +5557,7 @@ yyreduce: case 176: /* Line 1269 of yacc.c. */ -#line 2827 "querytransformparser.ypp" +#line 2863 "querytransformparser.ypp" { (yyval.expr) = (yyvsp[(2) - (2)].expr); } @@ -5529,7 +5565,7 @@ yyreduce: case 177: /* Line 1269 of yacc.c. */ -#line 2854 "querytransformparser.ypp" +#line 2890 "querytransformparser.ypp" { parseInfo->typeswitchSource.push((yyvsp[(3) - (4)].expr)); } @@ -5537,9 +5573,9 @@ yyreduce: case 178: /* Line 1269 of yacc.c. */ -#line 2858 "querytransformparser.ypp" +#line 2894 "querytransformparser.ypp" { - disallowedConstruct(parseInfo, (yyloc)); + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc)); parseInfo->typeswitchSource.pop(); (yyval.expr) = (yyvsp[(6) - (6)].expr); } @@ -5547,7 +5583,7 @@ yyreduce: case 179: /* Line 1269 of yacc.c. */ -#line 2865 "querytransformparser.ypp" +#line 2901 "querytransformparser.ypp" { if(!(yyvsp[(2) - (3)].qName).isNull()) { @@ -5559,7 +5595,7 @@ yyreduce: case 180: /* Line 1269 of yacc.c. */ -#line 2873 "querytransformparser.ypp" +#line 2909 "querytransformparser.ypp" { /* The variable shouldn't be in-scope for other case branches. */ if(!(yyvsp[(2) - (6)].qName).isNull()) @@ -5569,7 +5605,7 @@ yyreduce: case 181: /* Line 1269 of yacc.c. */ -#line 2879 "querytransformparser.ypp" +#line 2915 "querytransformparser.ypp" { const Expression::Ptr instanceOf(create(new InstanceOf(parseInfo->typeswitchSource.top(), (yyvsp[(3) - (8)].sequenceType)), (yyloc), parseInfo)); (yyval.expr) = create(new IfThenClause(instanceOf, (yyvsp[(6) - (8)].expr), (yyvsp[(8) - (8)].expr)), (yyloc), parseInfo); @@ -5578,7 +5614,7 @@ yyreduce: case 184: /* Line 1269 of yacc.c. */ -#line 2888 "querytransformparser.ypp" +#line 2924 "querytransformparser.ypp" { (yyval.qName) = QXmlName(); } @@ -5586,7 +5622,7 @@ yyreduce: case 185: /* Line 1269 of yacc.c. */ -#line 2893 "querytransformparser.ypp" +#line 2929 "querytransformparser.ypp" { (yyval.qName) = (yyvsp[(2) - (3)].qName); } @@ -5594,7 +5630,7 @@ yyreduce: case 186: /* Line 1269 of yacc.c. */ -#line 2898 "querytransformparser.ypp" +#line 2934 "querytransformparser.ypp" { (yyval.expr) = (yyvsp[(3) - (3)].expr); } @@ -5602,7 +5638,7 @@ yyreduce: case 187: /* Line 1269 of yacc.c. */ -#line 2902 "querytransformparser.ypp" +#line 2938 "querytransformparser.ypp" { if(!(yyvsp[(3) - (3)].qName).isNull()) { @@ -5615,7 +5651,7 @@ yyreduce: case 188: /* Line 1269 of yacc.c. */ -#line 2911 "querytransformparser.ypp" +#line 2947 "querytransformparser.ypp" { if(!(yyvsp[(3) - (6)].qName).isNull()) parseInfo->finalizePushedVariable(); @@ -5625,107 +5661,119 @@ yyreduce: case 189: /* Line 1269 of yacc.c. */ -#line 2918 "querytransformparser.ypp" +#line 2954 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = create(new IfThenClause((yyvsp[(3) - (8)].expr), (yyvsp[(6) - (8)].expr), (yyvsp[(8) - (8)].expr)), (yyloc), parseInfo); } break; case 191: /* Line 1269 of yacc.c. */ -#line 2924 "querytransformparser.ypp" +#line 2961 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = create(new OrExpression((yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)), (yyloc), parseInfo); } break; case 193: /* Line 1269 of yacc.c. */ -#line 2930 "querytransformparser.ypp" +#line 2968 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = create(new AndExpression((yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)), (yyloc), parseInfo); } break; case 199: /* Line 1269 of yacc.c. */ -#line 2941 "querytransformparser.ypp" +#line 2980 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = create(new RangeExpression((yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)), (yyloc), parseInfo); } break; case 201: /* Line 1269 of yacc.c. */ -#line 2947 "querytransformparser.ypp" +#line 2987 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = create(new ArithmeticExpression((yyvsp[(1) - (3)].expr), (yyvsp[(2) - (3)].enums.mathOperator), (yyvsp[(3) - (3)].expr)), (yyloc), parseInfo); } break; case 202: /* Line 1269 of yacc.c. */ -#line 2951 "querytransformparser.ypp" +#line 2992 "querytransformparser.ypp" {(yyval.enums.mathOperator) = AtomicMathematician::Add;} break; case 203: /* Line 1269 of yacc.c. */ -#line 2952 "querytransformparser.ypp" +#line 2993 "querytransformparser.ypp" {(yyval.enums.mathOperator) = AtomicMathematician::Substract;} break; case 205: /* Line 1269 of yacc.c. */ -#line 2956 "querytransformparser.ypp" +#line 2997 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = create(new ArithmeticExpression((yyvsp[(1) - (3)].expr), (yyvsp[(2) - (3)].enums.mathOperator), (yyvsp[(3) - (3)].expr)), (yyloc), parseInfo); } break; case 206: /* Line 1269 of yacc.c. */ -#line 2960 "querytransformparser.ypp" +#line 3002 "querytransformparser.ypp" {(yyval.enums.mathOperator) = AtomicMathematician::Multiply;} break; case 207: /* Line 1269 of yacc.c. */ -#line 2961 "querytransformparser.ypp" +#line 3003 "querytransformparser.ypp" {(yyval.enums.mathOperator) = AtomicMathematician::Div;} break; case 208: /* Line 1269 of yacc.c. */ -#line 2962 "querytransformparser.ypp" +#line 3004 "querytransformparser.ypp" {(yyval.enums.mathOperator) = AtomicMathematician::IDiv;} break; case 209: /* Line 1269 of yacc.c. */ -#line 2963 "querytransformparser.ypp" +#line 3005 "querytransformparser.ypp" {(yyval.enums.mathOperator) = AtomicMathematician::Mod;} break; case 211: /* Line 1269 of yacc.c. */ -#line 2967 "querytransformparser.ypp" +#line 3009 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 + | QXmlQuery::XPath20 + | QXmlQuery::XmlSchema11IdentityConstraintField + | QXmlQuery::XmlSchema11IdentityConstraintSelector), + parseInfo, (yyloc)); (yyval.expr) = create(new CombineNodes((yyvsp[(1) - (3)].expr), CombineNodes::Union, (yyvsp[(3) - (3)].expr)), (yyloc), parseInfo); } break; case 213: /* Line 1269 of yacc.c. */ -#line 2973 "querytransformparser.ypp" +#line 3020 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = create(new CombineNodes((yyvsp[(1) - (3)].expr), (yyvsp[(2) - (3)].enums.combinedNodeOp), (yyvsp[(3) - (3)].expr)), (yyloc), parseInfo); } break; case 216: /* Line 1269 of yacc.c. */ -#line 2981 "querytransformparser.ypp" +#line 3029 "querytransformparser.ypp" { (yyval.enums.combinedNodeOp) = CombineNodes::Intersect; } @@ -5733,7 +5781,7 @@ yyreduce: case 217: /* Line 1269 of yacc.c. */ -#line 2985 "querytransformparser.ypp" +#line 3033 "querytransformparser.ypp" { (yyval.enums.combinedNodeOp) = CombineNodes::Except; } @@ -5741,48 +5789,53 @@ yyreduce: case 219: /* Line 1269 of yacc.c. */ -#line 2991 "querytransformparser.ypp" +#line 3039 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = create(new InstanceOf((yyvsp[(1) - (4)].expr), - SequenceType::Ptr((yyvsp[(4) - (4)].sequenceType))), (yyloc), parseInfo); + SequenceType::Ptr((yyvsp[(4) - (4)].sequenceType))), (yyloc), parseInfo); } break; case 221: /* Line 1269 of yacc.c. */ -#line 2998 "querytransformparser.ypp" +#line 3047 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = create(new TreatAs((yyvsp[(1) - (4)].expr), (yyvsp[(4) - (4)].sequenceType)), (yyloc), parseInfo); } break; case 223: /* Line 1269 of yacc.c. */ -#line 3004 "querytransformparser.ypp" +#line 3054 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = create(new CastableAs((yyvsp[(1) - (4)].expr), (yyvsp[(4) - (4)].sequenceType)), (yyloc), parseInfo); } break; case 225: /* Line 1269 of yacc.c. */ -#line 3010 "querytransformparser.ypp" +#line 3061 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = create(new CastAs((yyvsp[(1) - (4)].expr), (yyvsp[(4) - (4)].sequenceType)), (yyloc), parseInfo); } break; case 227: /* Line 1269 of yacc.c. */ -#line 3016 "querytransformparser.ypp" +#line 3068 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = create(new UnaryExpression((yyvsp[(1) - (2)].enums.mathOperator), (yyvsp[(2) - (2)].expr), parseInfo->staticContext), (yyloc), parseInfo); } break; case 228: /* Line 1269 of yacc.c. */ -#line 3021 "querytransformparser.ypp" +#line 3074 "querytransformparser.ypp" { (yyval.enums.mathOperator) = AtomicMathematician::Add; } @@ -5790,7 +5843,7 @@ yyreduce: case 229: /* Line 1269 of yacc.c. */ -#line 3025 "querytransformparser.ypp" +#line 3078 "querytransformparser.ypp" { (yyval.enums.mathOperator) = AtomicMathematician::Substract; } @@ -5798,51 +5851,52 @@ yyreduce: case 233: /* Line 1269 of yacc.c. */ -#line 3034 "querytransformparser.ypp" +#line 3087 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = create(new GeneralComparison((yyvsp[(1) - (3)].expr), (yyvsp[(2) - (3)].enums.valueOperator), (yyvsp[(3) - (3)].expr), parseInfo->isBackwardsCompat.top()), (yyloc), parseInfo); } break; case 234: /* Line 1269 of yacc.c. */ -#line 3038 "querytransformparser.ypp" +#line 3092 "querytransformparser.ypp" {(yyval.enums.valueOperator) = AtomicComparator::OperatorEqual;} break; case 235: /* Line 1269 of yacc.c. */ -#line 3039 "querytransformparser.ypp" +#line 3093 "querytransformparser.ypp" {(yyval.enums.valueOperator) = AtomicComparator::OperatorNotEqual;} break; case 236: /* Line 1269 of yacc.c. */ -#line 3040 "querytransformparser.ypp" +#line 3094 "querytransformparser.ypp" {(yyval.enums.valueOperator) = AtomicComparator::OperatorGreaterOrEqual;} break; case 237: /* Line 1269 of yacc.c. */ -#line 3041 "querytransformparser.ypp" +#line 3095 "querytransformparser.ypp" {(yyval.enums.valueOperator) = AtomicComparator::OperatorGreaterThan;} break; case 238: /* Line 1269 of yacc.c. */ -#line 3042 "querytransformparser.ypp" +#line 3096 "querytransformparser.ypp" {(yyval.enums.valueOperator) = AtomicComparator::OperatorLessOrEqual;} break; case 239: /* Line 1269 of yacc.c. */ -#line 3043 "querytransformparser.ypp" +#line 3097 "querytransformparser.ypp" {(yyval.enums.valueOperator) = AtomicComparator::OperatorLessThan;} break; case 240: /* Line 1269 of yacc.c. */ -#line 3046 "querytransformparser.ypp" +#line 3100 "querytransformparser.ypp" { (yyval.expr) = create(new ValueComparison((yyvsp[(1) - (3)].expr), (yyvsp[(2) - (3)].enums.valueOperator), (yyvsp[(3) - (3)].expr)), (yyloc), parseInfo); } @@ -5850,43 +5904,43 @@ yyreduce: case 241: /* Line 1269 of yacc.c. */ -#line 3050 "querytransformparser.ypp" +#line 3104 "querytransformparser.ypp" {(yyval.enums.valueOperator) = AtomicComparator::OperatorEqual;} break; case 242: /* Line 1269 of yacc.c. */ -#line 3051 "querytransformparser.ypp" +#line 3105 "querytransformparser.ypp" {(yyval.enums.valueOperator) = AtomicComparator::OperatorNotEqual;} break; case 243: /* Line 1269 of yacc.c. */ -#line 3052 "querytransformparser.ypp" +#line 3106 "querytransformparser.ypp" {(yyval.enums.valueOperator) = AtomicComparator::OperatorGreaterOrEqual;} break; case 244: /* Line 1269 of yacc.c. */ -#line 3053 "querytransformparser.ypp" +#line 3107 "querytransformparser.ypp" {(yyval.enums.valueOperator) = AtomicComparator::OperatorGreaterThan;} break; case 245: /* Line 1269 of yacc.c. */ -#line 3054 "querytransformparser.ypp" +#line 3108 "querytransformparser.ypp" {(yyval.enums.valueOperator) = AtomicComparator::OperatorLessOrEqual;} break; case 246: /* Line 1269 of yacc.c. */ -#line 3055 "querytransformparser.ypp" +#line 3109 "querytransformparser.ypp" {(yyval.enums.valueOperator) = AtomicComparator::OperatorLessThan;} break; case 247: /* Line 1269 of yacc.c. */ -#line 3058 "querytransformparser.ypp" +#line 3112 "querytransformparser.ypp" { (yyval.expr) = create(new NodeComparison((yyvsp[(1) - (3)].expr), (yyvsp[(2) - (3)].enums.nodeOperator), (yyvsp[(3) - (3)].expr)), (yyloc), parseInfo); } @@ -5894,27 +5948,27 @@ yyreduce: case 248: /* Line 1269 of yacc.c. */ -#line 3062 "querytransformparser.ypp" +#line 3116 "querytransformparser.ypp" {(yyval.enums.nodeOperator) = QXmlNodeModelIndex::Is;} break; case 249: /* Line 1269 of yacc.c. */ -#line 3063 "querytransformparser.ypp" +#line 3117 "querytransformparser.ypp" {(yyval.enums.nodeOperator) = QXmlNodeModelIndex::Precedes;} break; case 250: /* Line 1269 of yacc.c. */ -#line 3064 "querytransformparser.ypp" +#line 3118 "querytransformparser.ypp" {(yyval.enums.nodeOperator) = QXmlNodeModelIndex::Follows;} break; case 251: /* Line 1269 of yacc.c. */ -#line 3067 "querytransformparser.ypp" +#line 3121 "querytransformparser.ypp" { - disallowedConstruct(parseInfo, (yyloc)); + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc)); parseInfo->staticContext->error(QtXmlPatterns::tr("The Schema Validation Feature is not supported. " "Hence, %1-expressions may not be used.") .arg(formatKeyword("validate")), @@ -5927,26 +5981,27 @@ yyreduce: case 252: /* Line 1269 of yacc.c. */ -#line 3080 "querytransformparser.ypp" +#line 3134 "querytransformparser.ypp" {(yyval.enums.validationMode) = Validate::Strict;} break; case 253: /* Line 1269 of yacc.c. */ -#line 3081 "querytransformparser.ypp" +#line 3135 "querytransformparser.ypp" {(yyval.enums.validationMode) = Validate::Strict;} break; case 254: /* Line 1269 of yacc.c. */ -#line 3082 "querytransformparser.ypp" +#line 3136 "querytransformparser.ypp" {(yyval.enums.validationMode) = Validate::Lax;} break; case 255: /* Line 1269 of yacc.c. */ -#line 3085 "querytransformparser.ypp" +#line 3139 "querytransformparser.ypp" { + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc)); /* We don't support any pragmas, so we only do the * necessary validation and use the fallback expression. */ @@ -5964,7 +6019,7 @@ yyreduce: case 256: /* Line 1269 of yacc.c. */ -#line 3101 "querytransformparser.ypp" +#line 3156 "querytransformparser.ypp" { (yyval.expr).reset(); } @@ -5972,7 +6027,7 @@ yyreduce: case 257: /* Line 1269 of yacc.c. */ -#line 3105 "querytransformparser.ypp" +#line 3160 "querytransformparser.ypp" { (yyval.expr) = (yyvsp[(2) - (3)].expr); } @@ -5980,15 +6035,15 @@ yyreduce: case 260: /* Line 1269 of yacc.c. */ -#line 3113 "querytransformparser.ypp" +#line 3168 "querytransformparser.ypp" { - disallowedConstruct(parseInfo, (yyloc)); + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc)); } break; case 263: /* Line 1269 of yacc.c. */ -#line 3121 "querytransformparser.ypp" +#line 3176 "querytransformparser.ypp" { /* This is "/step". That is, fn:root(self::node()) treat as document-node()/RelativePathExpr. */ (yyval.expr) = create(new Path(createRootExpression(parseInfo, (yyloc)), (yyvsp[(2) - (2)].expr)), (yyloc), parseInfo); @@ -5997,7 +6052,7 @@ yyreduce: case 264: /* Line 1269 of yacc.c. */ -#line 3127 "querytransformparser.ypp" +#line 3182 "querytransformparser.ypp" { (yyval.expr) = createSlashSlashPath(createRootExpression(parseInfo, (yyloc)), (yyvsp[(2) - (2)].expr), (yyloc), parseInfo); } @@ -6005,7 +6060,7 @@ yyreduce: case 265: /* Line 1269 of yacc.c. */ -#line 3131 "querytransformparser.ypp" +#line 3186 "querytransformparser.ypp" { /* This is "/". That is, fn:root(self::node()) treat as document-node(). */ (yyval.expr) = createRootExpression(parseInfo, (yyloc)); @@ -6014,7 +6069,7 @@ yyreduce: case 268: /* Line 1269 of yacc.c. */ -#line 3141 "querytransformparser.ypp" +#line 3196 "querytransformparser.ypp" { (yyval.expr) = create(new Path((yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr), (yyvsp[(2) - (3)].enums.pathKind)), (yyloc), parseInfo); } @@ -6022,7 +6077,7 @@ yyreduce: case 269: /* Line 1269 of yacc.c. */ -#line 3145 "querytransformparser.ypp" +#line 3200 "querytransformparser.ypp" { const Expression::Ptr orderBy(createReturnOrderBy((yyvsp[(4) - (7)].orderSpecs), (yyvsp[(6) - (7)].expr), parseInfo->orderStability.pop(), (yyloc), parseInfo)); @@ -6035,7 +6090,7 @@ yyreduce: case 270: /* Line 1269 of yacc.c. */ -#line 3154 "querytransformparser.ypp" +#line 3209 "querytransformparser.ypp" { (yyval.expr) = createSlashSlashPath((yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr), (yyloc), parseInfo); } @@ -6043,7 +6098,7 @@ yyreduce: case 271: /* Line 1269 of yacc.c. */ -#line 3159 "querytransformparser.ypp" +#line 3214 "querytransformparser.ypp" { (yyval.expr) = NodeSortExpression::wrapAround((yyvsp[(1) - (1)].expr), parseInfo->staticContext); } @@ -6051,7 +6106,7 @@ yyreduce: case 273: /* Line 1269 of yacc.c. */ -#line 3164 "querytransformparser.ypp" +#line 3219 "querytransformparser.ypp" { (yyval.expr) = create(new CurrentItemStore((yyvsp[(2) - (2)].expr)), (yyloc), parseInfo); } @@ -6059,7 +6114,7 @@ yyreduce: case 274: /* Line 1269 of yacc.c. */ -#line 3168 "querytransformparser.ypp" +#line 3223 "querytransformparser.ypp" { const xsDouble version = (yyvsp[(1) - (1)].sval).toDouble(); @@ -6071,7 +6126,7 @@ yyreduce: case 275: /* Line 1269 of yacc.c. */ -#line 3176 "querytransformparser.ypp" +#line 3231 "querytransformparser.ypp" { if((yyvsp[(2) - (3)].enums.Double) < 2) (yyval.expr) = createCompatStore((yyvsp[(3) - (3)].expr), (yyloc), parseInfo); @@ -6082,8 +6137,9 @@ yyreduce: case 276: /* Line 1269 of yacc.c. */ -#line 3183 "querytransformparser.ypp" +#line 3238 "querytransformparser.ypp" { + allowedIn(QXmlQuery::XSLT20, parseInfo, (yyloc)); Q_ASSERT(!(yyvsp[(2) - (5)].sval).isEmpty()); (yyval.expr) = create(new StaticBaseURIStore((yyvsp[(2) - (5)].sval), (yyvsp[(4) - (5)].expr)), (yyloc), parseInfo); } @@ -6091,8 +6147,9 @@ yyreduce: case 277: /* Line 1269 of yacc.c. */ -#line 3189 "querytransformparser.ypp" +#line 3245 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XSLT20), parseInfo, (yyloc)); parseInfo->resolvers.push(parseInfo->staticContext->namespaceBindings()); const NamespaceResolver::Ptr resolver(new DelegatingNamespaceResolver(parseInfo->staticContext->namespaceBindings())); resolver->addBinding(QXmlName(parseInfo->staticContext->namePool()->allocateNamespace((yyvsp[(5) - (6)].sval)), @@ -6104,7 +6161,7 @@ yyreduce: case 278: /* Line 1269 of yacc.c. */ -#line 3199 "querytransformparser.ypp" +#line 3256 "querytransformparser.ypp" { parseInfo->staticContext->setNamespaceBindings(parseInfo->resolvers.pop()); (yyval.expr) = (yyvsp[(8) - (9)].expr); @@ -6113,7 +6170,7 @@ yyreduce: case 279: /* Line 1269 of yacc.c. */ -#line 3204 "querytransformparser.ypp" +#line 3261 "querytransformparser.ypp" { (yyval.expr) = create(new CallTemplate((yyvsp[(2) - (5)].qName), parseInfo->templateWithParams), (yyloc), parseInfo); parseInfo->templateWithParametersHandled(); @@ -6123,7 +6180,7 @@ yyreduce: case 280: /* Line 1269 of yacc.c. */ -#line 3211 "querytransformparser.ypp" +#line 3268 "querytransformparser.ypp" { parseInfo->startParsingWithParam(); } @@ -6131,7 +6188,7 @@ yyreduce: case 281: /* Line 1269 of yacc.c. */ -#line 3215 "querytransformparser.ypp" +#line 3272 "querytransformparser.ypp" { parseInfo->endParsingWithParam(); } @@ -6139,42 +6196,42 @@ yyreduce: case 282: /* Line 1269 of yacc.c. */ -#line 3220 "querytransformparser.ypp" +#line 3277 "querytransformparser.ypp" { } break; case 283: /* Line 1269 of yacc.c. */ -#line 3223 "querytransformparser.ypp" +#line 3280 "querytransformparser.ypp" { } break; case 284: /* Line 1269 of yacc.c. */ -#line 3226 "querytransformparser.ypp" +#line 3283 "querytransformparser.ypp" { } break; case 285: /* Line 1269 of yacc.c. */ -#line 3230 "querytransformparser.ypp" +#line 3287 "querytransformparser.ypp" { } break; case 286: /* Line 1269 of yacc.c. */ -#line 3233 "querytransformparser.ypp" +#line 3290 "querytransformparser.ypp" { } break; case 287: /* Line 1269 of yacc.c. */ -#line 3237 "querytransformparser.ypp" +#line 3294 "querytransformparser.ypp" { /* Note, this grammar rule is invoked for @c xsl:param @em and @c * xsl:with-param. */ @@ -6242,7 +6299,7 @@ yyreduce: case 288: /* Line 1269 of yacc.c. */ -#line 3302 "querytransformparser.ypp" +#line 3359 "querytransformparser.ypp" { (yyval.enums.Bool) = false; } @@ -6250,7 +6307,7 @@ yyreduce: case 289: /* Line 1269 of yacc.c. */ -#line 3306 "querytransformparser.ypp" +#line 3363 "querytransformparser.ypp" { (yyval.enums.Bool) = true; } @@ -6258,7 +6315,7 @@ yyreduce: case 290: /* Line 1269 of yacc.c. */ -#line 3311 "querytransformparser.ypp" +#line 3368 "querytransformparser.ypp" { (yyval.expr) = Expression::Ptr(); } @@ -6266,7 +6323,7 @@ yyreduce: case 291: /* Line 1269 of yacc.c. */ -#line 3315 "querytransformparser.ypp" +#line 3372 "querytransformparser.ypp" { (yyval.expr) = (yyvsp[(2) - (2)].expr); } @@ -6274,7 +6331,7 @@ yyreduce: case 292: /* Line 1269 of yacc.c. */ -#line 3324 "querytransformparser.ypp" +#line 3381 "querytransformparser.ypp" { (yyval.enums.pathKind) = Path::RegularPath; } @@ -6282,7 +6339,7 @@ yyreduce: case 293: /* Line 1269 of yacc.c. */ -#line 3328 "querytransformparser.ypp" +#line 3385 "querytransformparser.ypp" { (yyval.enums.pathKind) = Path::XSLTForEach; } @@ -6290,7 +6347,7 @@ yyreduce: case 294: /* Line 1269 of yacc.c. */ -#line 3332 "querytransformparser.ypp" +#line 3389 "querytransformparser.ypp" { (yyval.enums.pathKind) = Path::ForApplyTemplate; } @@ -6298,7 +6355,7 @@ yyreduce: case 296: /* Line 1269 of yacc.c. */ -#line 3338 "querytransformparser.ypp" +#line 3395 "querytransformparser.ypp" { (yyval.expr) = create(GenericPredicate::create((yyvsp[(1) - (4)].expr), (yyvsp[(3) - (4)].expr), parseInfo->staticContext, fromYYLTYPE((yyloc), parseInfo)), (yyloc), parseInfo); } @@ -6306,7 +6363,7 @@ yyreduce: case 299: /* Line 1269 of yacc.c. */ -#line 3346 "querytransformparser.ypp" +#line 3403 "querytransformparser.ypp" { if((yyvsp[(1) - (1)].enums.axis) == QXmlNodeModelIndex::AxisAttribute) parseInfo->nodeTestSource = BuiltinTypes::attribute; @@ -6315,7 +6372,7 @@ yyreduce: case 300: /* Line 1269 of yacc.c. */ -#line 3351 "querytransformparser.ypp" +#line 3408 "querytransformparser.ypp" { if((yyvsp[(3) - (3)].itemType)) { @@ -6344,7 +6401,7 @@ yyreduce: case 304: /* Line 1269 of yacc.c. */ -#line 3381 "querytransformparser.ypp" +#line 3438 "querytransformparser.ypp" { if((yyvsp[(1) - (2)].enums.axis) == QXmlNodeModelIndex::AxisNamespace) { @@ -6356,84 +6413,114 @@ yyreduce: } else (yyval.enums.axis) = (yyvsp[(1) - (2)].enums.axis); + + switch((yyvsp[(1) - (2)].enums.axis)) + { + case QXmlNodeModelIndex::AxisAttribute: + { + allowedIn(QueryLanguages( QXmlQuery::XPath20 + | QXmlQuery::XQuery10 + | QXmlQuery::XmlSchema11IdentityConstraintField + | QXmlQuery::XSLT20), + parseInfo, (yyloc)); + break; + } + case QXmlNodeModelIndex::AxisChild: + { + allowedIn(QueryLanguages( QXmlQuery::XPath20 + | QXmlQuery::XQuery10 + | QXmlQuery::XmlSchema11IdentityConstraintField + | QXmlQuery::XmlSchema11IdentityConstraintSelector + | QXmlQuery::XSLT20), + parseInfo, (yyloc)); + break; + } + default: + { + allowedIn(QueryLanguages( QXmlQuery::XPath20 + | QXmlQuery::XQuery10 + | QXmlQuery::XSLT20), + parseInfo, (yyloc)); + } + } } break; case 305: /* Line 1269 of yacc.c. */ -#line 3394 "querytransformparser.ypp" +#line 3481 "querytransformparser.ypp" {(yyval.enums.axis) = QXmlNodeModelIndex::AxisAncestorOrSelf ;} break; case 306: /* Line 1269 of yacc.c. */ -#line 3395 "querytransformparser.ypp" +#line 3482 "querytransformparser.ypp" {(yyval.enums.axis) = QXmlNodeModelIndex::AxisAncestor ;} break; case 307: /* Line 1269 of yacc.c. */ -#line 3396 "querytransformparser.ypp" +#line 3483 "querytransformparser.ypp" {(yyval.enums.axis) = QXmlNodeModelIndex::AxisAttribute ;} break; case 308: /* Line 1269 of yacc.c. */ -#line 3397 "querytransformparser.ypp" +#line 3484 "querytransformparser.ypp" {(yyval.enums.axis) = QXmlNodeModelIndex::AxisChild ;} break; case 309: /* Line 1269 of yacc.c. */ -#line 3398 "querytransformparser.ypp" +#line 3485 "querytransformparser.ypp" {(yyval.enums.axis) = QXmlNodeModelIndex::AxisDescendantOrSelf;} break; case 310: /* Line 1269 of yacc.c. */ -#line 3399 "querytransformparser.ypp" +#line 3486 "querytransformparser.ypp" {(yyval.enums.axis) = QXmlNodeModelIndex::AxisDescendant ;} break; case 311: /* Line 1269 of yacc.c. */ -#line 3400 "querytransformparser.ypp" +#line 3487 "querytransformparser.ypp" {(yyval.enums.axis) = QXmlNodeModelIndex::AxisFollowing ;} break; case 312: /* Line 1269 of yacc.c. */ -#line 3401 "querytransformparser.ypp" +#line 3488 "querytransformparser.ypp" {(yyval.enums.axis) = QXmlNodeModelIndex::AxisPreceding ;} break; case 313: /* Line 1269 of yacc.c. */ -#line 3402 "querytransformparser.ypp" +#line 3489 "querytransformparser.ypp" {(yyval.enums.axis) = QXmlNodeModelIndex::AxisFollowingSibling;} break; case 314: /* Line 1269 of yacc.c. */ -#line 3403 "querytransformparser.ypp" +#line 3490 "querytransformparser.ypp" {(yyval.enums.axis) = QXmlNodeModelIndex::AxisPrecedingSibling;} break; case 315: /* Line 1269 of yacc.c. */ -#line 3404 "querytransformparser.ypp" +#line 3491 "querytransformparser.ypp" {(yyval.enums.axis) = QXmlNodeModelIndex::AxisParent ;} break; case 316: /* Line 1269 of yacc.c. */ -#line 3405 "querytransformparser.ypp" +#line 3492 "querytransformparser.ypp" {(yyval.enums.axis) = QXmlNodeModelIndex::AxisSelf ;} break; case 317: /* Line 1269 of yacc.c. */ -#line 3408 "querytransformparser.ypp" +#line 3495 "querytransformparser.ypp" { parseInfo->nodeTestSource = BuiltinTypes::attribute; } @@ -6441,8 +6528,9 @@ yyreduce: case 318: /* Line 1269 of yacc.c. */ -#line 3412 "querytransformparser.ypp" +#line 3499 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XSLT20 | QXmlQuery::XmlSchema11IdentityConstraintField), parseInfo, (yyloc)); (yyval.expr) = create(new AxisStep(QXmlNodeModelIndex::AxisAttribute, (yyvsp[(3) - (3)].itemType)), (yyloc), parseInfo); parseInfo->restoreNodeTestSource(); @@ -6451,7 +6539,7 @@ yyreduce: case 319: /* Line 1269 of yacc.c. */ -#line 3418 "querytransformparser.ypp" +#line 3506 "querytransformparser.ypp" { ItemType::Ptr nodeTest; @@ -6466,7 +6554,7 @@ yyreduce: case 320: /* Line 1269 of yacc.c. */ -#line 3429 "querytransformparser.ypp" +#line 3517 "querytransformparser.ypp" { (yyval.expr) = create(new AxisStep(QXmlNodeModelIndex::AxisAttribute, (yyvsp[(1) - (1)].itemType)), (yyloc), parseInfo); } @@ -6474,15 +6562,23 @@ yyreduce: case 322: /* Line 1269 of yacc.c. */ -#line 3436 "querytransformparser.ypp" +#line 3524 "querytransformparser.ypp" { (yyval.expr) = create(new AxisStep(QXmlNodeModelIndex::AxisParent, BuiltinTypes::node), (yyloc), parseInfo); } break; + case 324: +/* Line 1269 of yacc.c. */ +#line 3530 "querytransformparser.ypp" + { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); + } + break; + case 325: /* Line 1269 of yacc.c. */ -#line 3444 "querytransformparser.ypp" +#line 3535 "querytransformparser.ypp" { (yyval.itemType) = QNameTest::create(parseInfo->nodeTestSource, (yyvsp[(1) - (1)].qName)); } @@ -6490,7 +6586,7 @@ yyreduce: case 327: /* Line 1269 of yacc.c. */ -#line 3450 "querytransformparser.ypp" +#line 3541 "querytransformparser.ypp" { (yyval.itemType) = parseInfo->nodeTestSource; } @@ -6498,7 +6594,7 @@ yyreduce: case 328: /* Line 1269 of yacc.c. */ -#line 3454 "querytransformparser.ypp" +#line 3545 "querytransformparser.ypp" { const NamePool::Ptr np(parseInfo->staticContext->namePool()); const ReflectYYLTYPE ryy((yyloc), parseInfo); @@ -6511,8 +6607,9 @@ yyreduce: case 329: /* Line 1269 of yacc.c. */ -#line 3463 "querytransformparser.ypp" +#line 3554 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); const QXmlName::LocalNameCode c = parseInfo->staticContext->namePool()->allocateLocalName((yyvsp[(1) - (1)].sval)); (yyval.itemType) = LocalNameTest::create(parseInfo->nodeTestSource, c); } @@ -6520,15 +6617,16 @@ yyreduce: case 331: /* Line 1269 of yacc.c. */ -#line 3470 "querytransformparser.ypp" +#line 3562 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = create(GenericPredicate::create((yyvsp[(1) - (4)].expr), (yyvsp[(3) - (4)].expr), parseInfo->staticContext, fromYYLTYPE((yylsp[(4) - (4)]), parseInfo)), (yyloc), parseInfo); } break; case 339: /* Line 1269 of yacc.c. */ -#line 3482 "querytransformparser.ypp" +#line 3575 "querytransformparser.ypp" { (yyval.expr) = create(new ApplyTemplate(parseInfo->modeFor((yyvsp[(2) - (5)].qName)), parseInfo->templateWithParams, @@ -6541,7 +6639,7 @@ yyreduce: case 341: /* Line 1269 of yacc.c. */ -#line 3493 "querytransformparser.ypp" +#line 3586 "querytransformparser.ypp" { (yyval.expr) = create(new Literal(AtomicString::fromValue((yyvsp[(1) - (1)].sval))), (yyloc), parseInfo); } @@ -6549,31 +6647,34 @@ yyreduce: case 342: /* Line 1269 of yacc.c. */ -#line 3498 "querytransformparser.ypp" +#line 3591 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = createNumericLiteral((yyvsp[(1) - (1)].sval), (yyloc), parseInfo); } break; case 343: /* Line 1269 of yacc.c. */ -#line 3502 "querytransformparser.ypp" +#line 3596 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = createNumericLiteral((yyvsp[(1) - (1)].sval), (yyloc), parseInfo); } break; case 344: /* Line 1269 of yacc.c. */ -#line 3507 "querytransformparser.ypp" +#line 3602 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = resolveVariable((yyvsp[(2) - (2)].qName), (yyloc), parseInfo, false); } break; case 345: /* Line 1269 of yacc.c. */ -#line 3512 "querytransformparser.ypp" +#line 3608 "querytransformparser.ypp" { /* See: http://www.w3.org/TR/xpath20/#id-variables */ (yyval.qName) = parseInfo->staticContext->namePool()->allocateQName(QString(), (yyvsp[(1) - (1)].sval)); @@ -6582,7 +6683,7 @@ yyreduce: case 346: /* Line 1269 of yacc.c. */ -#line 3517 "querytransformparser.ypp" +#line 3613 "querytransformparser.ypp" { (yyval.qName) = (yyvsp[(1) - (1)].qName); } @@ -6590,23 +6691,25 @@ yyreduce: case 347: /* Line 1269 of yacc.c. */ -#line 3522 "querytransformparser.ypp" +#line 3618 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = (yyvsp[(2) - (3)].expr); } break; case 348: /* Line 1269 of yacc.c. */ -#line 3526 "querytransformparser.ypp" +#line 3623 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); (yyval.expr) = create(new EmptySequence, (yyloc), parseInfo); } break; case 349: /* Line 1269 of yacc.c. */ -#line 3531 "querytransformparser.ypp" +#line 3629 "querytransformparser.ypp" { (yyval.expr) = create(new ContextItem(), (yyloc), parseInfo); } @@ -6614,7 +6717,7 @@ yyreduce: case 350: /* Line 1269 of yacc.c. */ -#line 3536 "querytransformparser.ypp" +#line 3634 "querytransformparser.ypp" { (yyval.expr) = (yyvsp[(2) - (2)].expr); } @@ -6622,8 +6725,9 @@ yyreduce: case 351: /* Line 1269 of yacc.c. */ -#line 3541 "querytransformparser.ypp" +#line 3639 "querytransformparser.ypp" { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); if(XPathHelper::isReservedNamespace((yyvsp[(1) - (4)].qName).namespaceURI()) || (yyvsp[(1) - (4)].qName).namespaceURI() == StandardNamespaces::InternalXSLT) { /* We got a call to a builtin function. */ const ReflectYYLTYPE ryy((yyloc), parseInfo); @@ -6653,7 +6757,7 @@ yyreduce: case 352: /* Line 1269 of yacc.c. */ -#line 3569 "querytransformparser.ypp" +#line 3668 "querytransformparser.ypp" { (yyval.expressionList) = Expression::List(); } @@ -6661,7 +6765,7 @@ yyreduce: case 353: /* Line 1269 of yacc.c. */ -#line 3574 "querytransformparser.ypp" +#line 3673 "querytransformparser.ypp" { Expression::List list; list.append((yyvsp[(1) - (1)].expr)); @@ -6671,15 +6775,15 @@ yyreduce: case 355: /* Line 1269 of yacc.c. */ -#line 3583 "querytransformparser.ypp" +#line 3682 "querytransformparser.ypp" { - disallowedConstruct(parseInfo, (yyloc)); + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc)); } break; case 360: /* Line 1269 of yacc.c. */ -#line 3624 "querytransformparser.ypp" +#line 3726 "querytransformparser.ypp" { (yyval.enums.tokenizerPosition) = parseInfo->tokenizer->commenceScanOnly(); parseInfo->scanOnlyStack.push(true); @@ -6688,7 +6792,7 @@ yyreduce: case 361: /* Line 1269 of yacc.c. */ -#line 3633 "querytransformparser.ypp" +#line 3735 "querytransformparser.ypp" { ++parseInfo->elementConstructorDepth; Expression::List constructors; @@ -6836,7 +6940,7 @@ yyreduce: case 362: /* Line 1269 of yacc.c. */ -#line 3779 "querytransformparser.ypp" +#line 3881 "querytransformparser.ypp" { /* We add the content constructor after the attribute constructors. This might result * in nested ExpressionSequences, but it will be optimized away later on. */ @@ -6935,7 +7039,7 @@ yyreduce: case 363: /* Line 1269 of yacc.c. */ -#line 3875 "querytransformparser.ypp" +#line 3977 "querytransformparser.ypp" { (yyval.expr) = create(new EmptySequence(), (yyloc), parseInfo); } @@ -6943,7 +7047,7 @@ yyreduce: case 364: /* Line 1269 of yacc.c. */ -#line 3879 "querytransformparser.ypp" +#line 3981 "querytransformparser.ypp" { if(!(yyvsp[(4) - (5)].qName).isLexicallyEqual(parseInfo->tagStack.top())) { @@ -6965,7 +7069,7 @@ yyreduce: case 365: /* Line 1269 of yacc.c. */ -#line 3898 "querytransformparser.ypp" +#line 4000 "querytransformparser.ypp" { (yyval.attributeHolders) = AttributeHolderVector(); } @@ -6973,7 +7077,7 @@ yyreduce: case 366: /* Line 1269 of yacc.c. */ -#line 3902 "querytransformparser.ypp" +#line 4004 "querytransformparser.ypp" { (yyvsp[(1) - (2)].attributeHolders).append((yyvsp[(2) - (2)].attributeHolder)); (yyval.attributeHolders) = (yyvsp[(1) - (2)].attributeHolders); @@ -6982,7 +7086,7 @@ yyreduce: case 367: /* Line 1269 of yacc.c. */ -#line 3908 "querytransformparser.ypp" +#line 4010 "querytransformparser.ypp" { (yyval.attributeHolder) = qMakePair((yyvsp[(1) - (3)].sval), (yyvsp[(3) - (3)].expr)); } @@ -6990,7 +7094,7 @@ yyreduce: case 368: /* Line 1269 of yacc.c. */ -#line 3913 "querytransformparser.ypp" +#line 4015 "querytransformparser.ypp" { (yyval.expr) = createDirAttributeValue((yyvsp[(2) - (3)].expressionList), parseInfo, (yyloc)); } @@ -6998,7 +7102,7 @@ yyreduce: case 369: /* Line 1269 of yacc.c. */ -#line 3918 "querytransformparser.ypp" +#line 4020 "querytransformparser.ypp" { (yyval.expr) = createDirAttributeValue((yyvsp[(2) - (3)].expressionList), parseInfo, (yyloc)); } @@ -7006,7 +7110,7 @@ yyreduce: case 370: /* Line 1269 of yacc.c. */ -#line 3923 "querytransformparser.ypp" +#line 4025 "querytransformparser.ypp" { (yyval.expressionList) = Expression::List(); } @@ -7014,7 +7118,7 @@ yyreduce: case 371: /* Line 1269 of yacc.c. */ -#line 3927 "querytransformparser.ypp" +#line 4029 "querytransformparser.ypp" { Expression::Ptr content((yyvsp[(1) - (2)].expr)); @@ -7028,7 +7132,7 @@ yyreduce: case 372: /* Line 1269 of yacc.c. */ -#line 3937 "querytransformparser.ypp" +#line 4039 "querytransformparser.ypp" { (yyvsp[(2) - (2)].expressionList).prepend(create(new Literal(AtomicString::fromValue((yyvsp[(1) - (2)].sval))), (yyloc), parseInfo)); (yyval.expressionList) = (yyvsp[(2) - (2)].expressionList); @@ -7037,7 +7141,7 @@ yyreduce: case 373: /* Line 1269 of yacc.c. */ -#line 3943 "querytransformparser.ypp" +#line 4045 "querytransformparser.ypp" { (yyval.expressionList) = Expression::List(); parseInfo->isPreviousEnclosedExpr = false; @@ -7046,7 +7150,7 @@ yyreduce: case 374: /* Line 1269 of yacc.c. */ -#line 3948 "querytransformparser.ypp" +#line 4050 "querytransformparser.ypp" { (yyvsp[(1) - (2)].expressionList).append((yyvsp[(2) - (2)].expr)); (yyval.expressionList) = (yyvsp[(1) - (2)].expressionList); @@ -7056,7 +7160,7 @@ yyreduce: case 375: /* Line 1269 of yacc.c. */ -#line 3954 "querytransformparser.ypp" +#line 4056 "querytransformparser.ypp" { if(parseInfo->staticContext->boundarySpacePolicy() == StaticContext::BSPStrip && XPathHelper::isWhitespaceOnly((yyvsp[(2) - (2)].sval))) @@ -7074,7 +7178,7 @@ yyreduce: case 376: /* Line 1269 of yacc.c. */ -#line 3968 "querytransformparser.ypp" +#line 4070 "querytransformparser.ypp" { (yyvsp[(1) - (2)].expressionList).append(create(new TextNodeConstructor(create(new Literal(AtomicString::fromValue((yyvsp[(2) - (2)].sval))), (yyloc), parseInfo)), (yyloc), parseInfo)); (yyval.expressionList) = (yyvsp[(1) - (2)].expressionList); @@ -7084,7 +7188,7 @@ yyreduce: case 377: /* Line 1269 of yacc.c. */ -#line 3974 "querytransformparser.ypp" +#line 4076 "querytransformparser.ypp" { /* We insert a text node constructor that send an empty text node between * the two enclosed expressions, in order to ensure that no space is inserted. @@ -7104,7 +7208,7 @@ yyreduce: case 378: /* Line 1269 of yacc.c. */ -#line 3991 "querytransformparser.ypp" +#line 4093 "querytransformparser.ypp" { (yyval.expr) = create(new CommentConstructor(create(new Literal(AtomicString::fromValue((yyvsp[(2) - (2)].sval))), (yyloc), parseInfo)), (yyloc), parseInfo); } @@ -7112,7 +7216,7 @@ yyreduce: case 379: /* Line 1269 of yacc.c. */ -#line 3996 "querytransformparser.ypp" +#line 4098 "querytransformparser.ypp" { const ReflectYYLTYPE ryy((yyloc), parseInfo); NCNameConstructor::validateTargetNameelementConstructorDepth; @@ -7147,10 +7251,10 @@ yyreduce: case 389: /* Line 1269 of yacc.c. */ -#line 4029 "querytransformparser.ypp" +#line 4131 "querytransformparser.ypp" { Q_ASSERT(5); - disallowedConstruct(parseInfo, (yyloc), (yyvsp[(2) - (5)].enums.Bool)); + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc), (yyvsp[(2) - (5)].enums.Bool)); Expression::Ptr effExpr; @@ -7184,7 +7288,7 @@ yyreduce: case 390: /* Line 1269 of yacc.c. */ -#line 4063 "querytransformparser.ypp" +#line 4165 "querytransformparser.ypp" { (yyval.enums.Bool) = false; } @@ -7192,7 +7296,7 @@ yyreduce: case 391: /* Line 1269 of yacc.c. */ -#line 4067 "querytransformparser.ypp" +#line 4169 "querytransformparser.ypp" { (yyval.enums.Bool) = true; } @@ -7200,9 +7304,9 @@ yyreduce: case 392: /* Line 1269 of yacc.c. */ -#line 4075 "querytransformparser.ypp" +#line 4177 "querytransformparser.ypp" { - disallowedConstruct(parseInfo, (yyloc), (yyvsp[(2) - (4)].enums.Bool)); + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc), (yyvsp[(2) - (4)].enums.Bool)); const Expression::Ptr name(create(new AttributeNameValidator((yyvsp[(3) - (4)].expr)), (yyloc), parseInfo)); @@ -7215,7 +7319,7 @@ yyreduce: case 393: /* Line 1269 of yacc.c. */ -#line 4087 "querytransformparser.ypp" +#line 4189 "querytransformparser.ypp" { (yyval.expr) = create(new TextNodeConstructor(createSimpleContent((yyvsp[(3) - (3)].expr), (yyloc), parseInfo)), (yyloc), parseInfo); } @@ -7223,9 +7327,9 @@ yyreduce: case 394: /* Line 1269 of yacc.c. */ -#line 4092 "querytransformparser.ypp" +#line 4194 "querytransformparser.ypp" { - disallowedConstruct(parseInfo, (yyloc), (yyvsp[(2) - (3)].enums.Bool)); + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc), (yyvsp[(2) - (3)].enums.Bool)); (yyval.expr) = create(new CommentConstructor(createSimpleContent((yyvsp[(3) - (3)].expr), (yyloc), parseInfo)), (yyloc), parseInfo); } @@ -7233,9 +7337,9 @@ yyreduce: case 395: /* Line 1269 of yacc.c. */ -#line 4099 "querytransformparser.ypp" +#line 4201 "querytransformparser.ypp" { - disallowedConstruct(parseInfo, (yyloc), (yyvsp[(2) - (3)].expr)); + allowedIn(QXmlQuery::XQuery10, parseInfo, (yyloc), (yyvsp[(2) - (3)].expr)); if((yyvsp[(3) - (3)].expr)) { @@ -7248,7 +7352,7 @@ yyreduce: case 396: /* Line 1269 of yacc.c. */ -#line 4110 "querytransformparser.ypp" +#line 4212 "querytransformparser.ypp" { parseInfo->nodeTestSource = BuiltinTypes::attribute; } @@ -7256,7 +7360,7 @@ yyreduce: case 397: /* Line 1269 of yacc.c. */ -#line 4114 "querytransformparser.ypp" +#line 4216 "querytransformparser.ypp" { parseInfo->restoreNodeTestSource(); } @@ -7264,7 +7368,7 @@ yyreduce: case 398: /* Line 1269 of yacc.c. */ -#line 4117 "querytransformparser.ypp" +#line 4219 "querytransformparser.ypp" { (yyval.expr) = create(new Literal(toItem(QNameValue::fromValue(parseInfo->staticContext->namePool(), (yyvsp[(2) - (3)].qName)))), (yyloc), parseInfo); } @@ -7272,7 +7376,7 @@ yyreduce: case 400: /* Line 1269 of yacc.c. */ -#line 4123 "querytransformparser.ypp" +#line 4225 "querytransformparser.ypp" { (yyval.expr) = create(new Literal(toItem(QNameValue::fromValue(parseInfo->staticContext->namePool(), (yyvsp[(1) - (1)].qName)))), (yyloc), parseInfo); } @@ -7280,7 +7384,7 @@ yyreduce: case 402: /* Line 1269 of yacc.c. */ -#line 4129 "querytransformparser.ypp" +#line 4231 "querytransformparser.ypp" { if(BuiltinTypes::xsQName->xdtTypeMatches((yyvsp[(1) - (1)].expr)->staticType()->itemType())) (yyval.expr) = (yyvsp[(1) - (1)].expr); @@ -7295,7 +7399,7 @@ yyreduce: case 403: /* Line 1269 of yacc.c. */ -#line 4144 "querytransformparser.ypp" +#line 4246 "querytransformparser.ypp" { (yyval.expr) = create(new NCNameConstructor(create(new Literal(AtomicString::fromValue((yyvsp[(1) - (1)].sval))), (yyloc), parseInfo)), (yyloc), parseInfo); } @@ -7303,7 +7407,7 @@ yyreduce: case 404: /* Line 1269 of yacc.c. */ -#line 4148 "querytransformparser.ypp" +#line 4250 "querytransformparser.ypp" { (yyval.expr) = create(new NCNameConstructor((yyvsp[(1) - (1)].expr)), (yyloc), parseInfo); } @@ -7311,7 +7415,7 @@ yyreduce: case 405: /* Line 1269 of yacc.c. */ -#line 4157 "querytransformparser.ypp" +#line 4259 "querytransformparser.ypp" { (yyval.expr) = create(new ComputedNamespaceConstructor((yyvsp[(2) - (3)].expr), (yyvsp[(3) - (3)].expr)), (yyloc), parseInfo); } @@ -7319,7 +7423,7 @@ yyreduce: case 406: /* Line 1269 of yacc.c. */ -#line 4162 "querytransformparser.ypp" +#line 4264 "querytransformparser.ypp" { (yyval.sequenceType) = makeGenericSequenceType((yyvsp[(1) - (1)].itemType), Cardinality::exactlyOne()); } @@ -7327,7 +7431,7 @@ yyreduce: case 407: /* Line 1269 of yacc.c. */ -#line 4166 "querytransformparser.ypp" +#line 4268 "querytransformparser.ypp" { (yyval.sequenceType) = makeGenericSequenceType((yyvsp[(1) - (2)].itemType), Cardinality::zeroOrOne()); } @@ -7335,7 +7439,7 @@ yyreduce: case 408: /* Line 1269 of yacc.c. */ -#line 4171 "querytransformparser.ypp" +#line 4273 "querytransformparser.ypp" { (yyval.sequenceType) = CommonSequenceTypes::ZeroOrMoreItems; } @@ -7343,7 +7447,7 @@ yyreduce: case 409: /* Line 1269 of yacc.c. */ -#line 4175 "querytransformparser.ypp" +#line 4277 "querytransformparser.ypp" { (yyval.sequenceType) = (yyvsp[(2) - (2)].sequenceType); } @@ -7351,7 +7455,7 @@ yyreduce: case 410: /* Line 1269 of yacc.c. */ -#line 4180 "querytransformparser.ypp" +#line 4282 "querytransformparser.ypp" { (yyval.sequenceType) = makeGenericSequenceType((yyvsp[(1) - (2)].itemType), (yyvsp[(2) - (2)].cardinality)); } @@ -7359,7 +7463,7 @@ yyreduce: case 411: /* Line 1269 of yacc.c. */ -#line 4185 "querytransformparser.ypp" +#line 4287 "querytransformparser.ypp" { (yyval.sequenceType) = CommonSequenceTypes::Empty; } @@ -7367,31 +7471,31 @@ yyreduce: case 412: /* Line 1269 of yacc.c. */ -#line 4189 "querytransformparser.ypp" +#line 4291 "querytransformparser.ypp" {(yyval.cardinality) = Cardinality::exactlyOne();} break; case 413: /* Line 1269 of yacc.c. */ -#line 4190 "querytransformparser.ypp" +#line 4292 "querytransformparser.ypp" {(yyval.cardinality) = Cardinality::oneOrMore();} break; case 414: /* Line 1269 of yacc.c. */ -#line 4191 "querytransformparser.ypp" +#line 4293 "querytransformparser.ypp" {(yyval.cardinality) = Cardinality::zeroOrMore();} break; case 415: /* Line 1269 of yacc.c. */ -#line 4192 "querytransformparser.ypp" +#line 4294 "querytransformparser.ypp" {(yyval.cardinality) = Cardinality::zeroOrOne();} break; case 419: /* Line 1269 of yacc.c. */ -#line 4198 "querytransformparser.ypp" +#line 4300 "querytransformparser.ypp" { (yyval.itemType) = BuiltinTypes::item; } @@ -7399,7 +7503,7 @@ yyreduce: case 420: /* Line 1269 of yacc.c. */ -#line 4203 "querytransformparser.ypp" +#line 4305 "querytransformparser.ypp" { const SchemaType::Ptr t(parseInfo->staticContext->schemaDefinitions()->createSchemaType((yyvsp[(1) - (1)].qName))); @@ -7435,7 +7539,7 @@ yyreduce: case 428: /* Line 1269 of yacc.c. */ -#line 4247 "querytransformparser.ypp" +#line 4349 "querytransformparser.ypp" { (yyval.itemType) = BuiltinTypes::node; } @@ -7443,7 +7547,7 @@ yyreduce: case 429: /* Line 1269 of yacc.c. */ -#line 4252 "querytransformparser.ypp" +#line 4354 "querytransformparser.ypp" { (yyval.itemType) = BuiltinTypes::document; } @@ -7451,7 +7555,7 @@ yyreduce: case 430: /* Line 1269 of yacc.c. */ -#line 4257 "querytransformparser.ypp" +#line 4359 "querytransformparser.ypp" { // TODO support for document element testing (yyval.itemType) = BuiltinTypes::document; @@ -7460,7 +7564,7 @@ yyreduce: case 433: /* Line 1269 of yacc.c. */ -#line 4266 "querytransformparser.ypp" +#line 4368 "querytransformparser.ypp" { (yyval.itemType) = BuiltinTypes::text; } @@ -7468,7 +7572,7 @@ yyreduce: case 434: /* Line 1269 of yacc.c. */ -#line 4271 "querytransformparser.ypp" +#line 4373 "querytransformparser.ypp" { (yyval.itemType) = BuiltinTypes::comment; } @@ -7476,7 +7580,7 @@ yyreduce: case 435: /* Line 1269 of yacc.c. */ -#line 4276 "querytransformparser.ypp" +#line 4378 "querytransformparser.ypp" { (yyval.itemType) = BuiltinTypes::pi; } @@ -7484,7 +7588,7 @@ yyreduce: case 436: /* Line 1269 of yacc.c. */ -#line 4281 "querytransformparser.ypp" +#line 4383 "querytransformparser.ypp" { (yyval.itemType) = LocalNameTest::create(BuiltinTypes::pi, parseInfo->staticContext->namePool()->allocateLocalName((yyvsp[(3) - (4)].sval))); } @@ -7492,7 +7596,7 @@ yyreduce: case 437: /* Line 1269 of yacc.c. */ -#line 4286 "querytransformparser.ypp" +#line 4388 "querytransformparser.ypp" { if(QXmlUtils::isNCName((yyvsp[(3) - (4)].sval))) { @@ -7511,7 +7615,7 @@ yyreduce: case 440: /* Line 1269 of yacc.c. */ -#line 4305 "querytransformparser.ypp" +#line 4407 "querytransformparser.ypp" { (yyval.itemType) = BuiltinTypes::attribute; } @@ -7519,7 +7623,7 @@ yyreduce: case 441: /* Line 1269 of yacc.c. */ -#line 4310 "querytransformparser.ypp" +#line 4412 "querytransformparser.ypp" { (yyval.itemType) = BuiltinTypes::attribute; } @@ -7527,7 +7631,7 @@ yyreduce: case 442: /* Line 1269 of yacc.c. */ -#line 4315 "querytransformparser.ypp" +#line 4417 "querytransformparser.ypp" { (yyval.itemType) = QNameTest::create(BuiltinTypes::attribute, (yyvsp[(3) - (4)].qName)); } @@ -7535,7 +7639,7 @@ yyreduce: case 443: /* Line 1269 of yacc.c. */ -#line 4319 "querytransformparser.ypp" +#line 4421 "querytransformparser.ypp" { const SchemaType::Ptr t(parseInfo->staticContext->schemaDefinitions()->createSchemaType((yyvsp[(5) - (6)].qName))); @@ -7551,7 +7655,7 @@ yyreduce: case 444: /* Line 1269 of yacc.c. */ -#line 4331 "querytransformparser.ypp" +#line 4433 "querytransformparser.ypp" { const SchemaType::Ptr t(parseInfo->staticContext->schemaDefinitions()->createSchemaType((yyvsp[(5) - (6)].qName))); @@ -7567,7 +7671,7 @@ yyreduce: case 445: /* Line 1269 of yacc.c. */ -#line 4344 "querytransformparser.ypp" +#line 4446 "querytransformparser.ypp" { parseInfo->staticContext->error(QtXmlPatterns::tr("%1 is not in the in-scope attribute " "declarations. Note that the schema import " @@ -7580,7 +7684,7 @@ yyreduce: case 446: /* Line 1269 of yacc.c. */ -#line 4354 "querytransformparser.ypp" +#line 4456 "querytransformparser.ypp" { (yyval.itemType) = BuiltinTypes::element; } @@ -7588,7 +7692,7 @@ yyreduce: case 447: /* Line 1269 of yacc.c. */ -#line 4359 "querytransformparser.ypp" +#line 4461 "querytransformparser.ypp" { (yyval.itemType) = BuiltinTypes::element; } @@ -7596,7 +7700,7 @@ yyreduce: case 448: /* Line 1269 of yacc.c. */ -#line 4364 "querytransformparser.ypp" +#line 4466 "querytransformparser.ypp" { (yyval.itemType) = QNameTest::create(BuiltinTypes::element, (yyvsp[(3) - (4)].qName)); } @@ -7604,7 +7708,7 @@ yyreduce: case 449: /* Line 1269 of yacc.c. */ -#line 4369 "querytransformparser.ypp" +#line 4471 "querytransformparser.ypp" { const SchemaType::Ptr t(parseInfo->staticContext->schemaDefinitions()->createSchemaType((yyvsp[(5) - (7)].qName))); @@ -7621,7 +7725,7 @@ yyreduce: case 450: /* Line 1269 of yacc.c. */ -#line 4383 "querytransformparser.ypp" +#line 4485 "querytransformparser.ypp" { const SchemaType::Ptr t(parseInfo->staticContext->schemaDefinitions()->createSchemaType((yyvsp[(5) - (7)].qName))); @@ -7638,7 +7742,7 @@ yyreduce: case 453: /* Line 1269 of yacc.c. */ -#line 4400 "querytransformparser.ypp" +#line 4502 "querytransformparser.ypp" { parseInfo->staticContext->error(QtXmlPatterns::tr("%1 is not in the in-scope attribute " "declarations. Note that the schema import " @@ -7651,7 +7755,7 @@ yyreduce: case 455: /* Line 1269 of yacc.c. */ -#line 4412 "querytransformparser.ypp" +#line 4514 "querytransformparser.ypp" { (yyval.qName) = parseInfo->staticContext->namePool()->allocateQName(StandardNamespaces::empty, (yyvsp[(1) - (1)].sval)); } @@ -7659,7 +7763,7 @@ yyreduce: case 457: /* Line 1269 of yacc.c. */ -#line 4424 "querytransformparser.ypp" +#line 4526 "querytransformparser.ypp" { if(parseInfo->nodeTestSource == BuiltinTypes::element) (yyval.qName) = parseInfo->staticContext->namePool()->allocateQName(parseInfo->staticContext->namespaceBindings()->lookupNamespaceURI(StandardPrefixes::empty), (yyvsp[(1) - (1)].sval)); @@ -7670,7 +7774,7 @@ yyreduce: case 462: /* Line 1269 of yacc.c. */ -#line 4438 "querytransformparser.ypp" +#line 4540 "querytransformparser.ypp" { (yyval.qName) = parseInfo->staticContext->namePool()->allocateQName(parseInfo->staticContext->defaultFunctionNamespace(), (yyvsp[(1) - (1)].sval)); } @@ -7678,7 +7782,7 @@ yyreduce: case 463: /* Line 1269 of yacc.c. */ -#line 4442 "querytransformparser.ypp" +#line 4544 "querytransformparser.ypp" { (yyval.qName) = parseInfo->staticContext->namePool()->allocateQName(StandardNamespaces::InternalXSLT, (yyvsp[(2) - (2)].sval)); } @@ -7686,7 +7790,7 @@ yyreduce: case 466: /* Line 1269 of yacc.c. */ -#line 4450 "querytransformparser.ypp" +#line 4552 "querytransformparser.ypp" { parseInfo->staticContext->error(QtXmlPatterns::tr("The name of an extension expression must be in " "a namespace."), @@ -7694,9 +7798,25 @@ yyreduce: } break; + case 469: +/* Line 1269 of yacc.c. */ +#line 4562 "querytransformparser.ypp" + { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); + } + break; + + case 470: +/* Line 1269 of yacc.c. */ +#line 4566 "querytransformparser.ypp" + { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, (yyloc)); + } + break; + case 471: /* Line 1269 of yacc.c. */ -#line 4463 "querytransformparser.ypp" +#line 4571 "querytransformparser.ypp" { const ReflectYYLTYPE ryy((yyloc), parseInfo); @@ -7712,7 +7832,7 @@ yyreduce: case 472: /* Line 1269 of yacc.c. */ -#line 4475 "querytransformparser.ypp" +#line 4583 "querytransformparser.ypp" { (yyval.qName) = parseInfo->staticContext->namePool()->fromClarkName((yyvsp[(1) - (1)].sval)); } @@ -7720,7 +7840,7 @@ yyreduce: /* Line 1269 of yacc.c. */ -#line 7643 "qquerytransformparser.cpp" +#line 7763 "qquerytransformparser.cpp" default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); @@ -7938,7 +8058,7 @@ yyreturn: /* Line 1486 of yacc.c. */ -#line 4479 "querytransformparser.ypp" +#line 4587 "querytransformparser.ypp" QString Tokenizer::tokenToString(const Token &token) diff --git a/src/xmlpatterns/parser/qquerytransformparser_p.h b/src/xmlpatterns/parser/qquerytransformparser_p.h index fcf8896..759c39f 100644 --- a/src/xmlpatterns/parser/qquerytransformparser_p.h +++ b/src/xmlpatterns/parser/qquerytransformparser_p.h @@ -49,6 +49,27 @@ // // We mean it. +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + /* A Bison parser, made by GNU Bison 2.3a. */ /* Skeleton interface for Bison's Yacc-like parsers in C @@ -104,6 +125,25 @@ # undef SELF #endif +/* These tokens are defined to nothing on Windows because they're + * used in their documentation parser, for use in things like: + * + * int foo(IN char* name, OUT char* path); + * + * Hence this un-break fix. Note that this file was auto generated. */ +#ifdef IN +# undef IN +#endif +#ifdef INSTANCE +# undef INSTANCE +#endif +#ifdef STRICT +# undef STRICT +#endif +#ifdef SELF +# undef SELF +#endif + /* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE diff --git a/src/xmlpatterns/parser/querytransformparser.ypp b/src/xmlpatterns/parser/querytransformparser.ypp index 93974a4..e4f6b2d 100644 --- a/src/xmlpatterns/parser/querytransformparser.ypp +++ b/src/xmlpatterns/parser/querytransformparser.ypp @@ -227,11 +227,18 @@ static inline QSourceLocation fromYYLTYPE(const YYLTYPE &sourceLocator, } /** + * @internal + * @relates QXmlQuery + */ +typedef QFlags QueryLanguages; + +/** * @short Flags invalid expressions and declarations in the currently * parsed language. * - * Since this grammar is used for several languages: XQuery 1.0, XSL-T 2.0 and - * XPath 2.0 inside XSL-T, it is the union of all the constructs in these + * Since this grammar is used for several languages: XQuery 1.0, XSL-T 2.0, and + * XPath 2.0 inside XSL-T, and field and selector patterns in W3C XML Schema's + * identity constraints, it is the union of all the constructs in these * languages. However, when dealing with each language individually, we * regularly need to disallow some expressions, such as direct element * constructors when parsing XSL-T, or the typeswitch when parsing XPath. @@ -242,19 +249,46 @@ static inline QSourceLocation fromYYLTYPE(const YYLTYPE &sourceLocator, * instance the @c let clause, should not be flagged as an error, because it's * used for internal purposes. * - * Hence, this function is called from each expression and declaration which is - * unavailable in XPath. + * Hence, this function is called from each expression and declaration with @p + * allowedLanguages stating what languages it is allowed in. * * If @p isInternal is @c true, no error is raised. Otherwise, if the current - * language is not XQuery, an error is raised. + * language is not in @p allowedLanguages, an error is raised. */ -static void disallowedConstruct(const ParserContext *const parseInfo, - const YYLTYPE &sourceLocator, - const bool isInternal = false) +static void allowedIn(const QueryLanguages allowedLanguages, + const ParserContext *const parseInfo, + const YYLTYPE &sourceLocator, + const bool isInternal = false) { - if(!isInternal && parseInfo->languageAccent != QXmlQuery::XQuery10) + /* We treat XPath 2.0 as a subset of XSL-T 2.0, so if XPath 2.0 is allowed + * and XSL-T is the language, it's ok. */ + if(!isInternal && + (!allowedLanguages.testFlag(parseInfo->languageAccent) && !(allowedLanguages.testFlag(QXmlQuery::XPath20) && parseInfo->languageAccent == QXmlQuery::XSLT20))) { - parseInfo->staticContext->error(QtXmlPatterns::tr("A construct was encountered which only is allowed in XQuery."), + + QString langName; + + switch(parseInfo->languageAccent) + { + case QXmlQuery::XPath20: + langName = QLatin1String("XPath 2.0"); + break; + case QXmlQuery::XSLT20: + langName = QLatin1String("XSL-T 2.0"); + break; + case QXmlQuery::XQuery10: + langName = QLatin1String("XQuery 1.0"); + break; + case QXmlQuery::XmlSchema11IdentityConstraintSelector: + langName = QtXmlPatterns::tr("W3C XML Schema identity constraint selector"); + break; + case QXmlQuery::XmlSchema11IdentityConstraintField: + langName = QtXmlPatterns::tr("W3C XML Schema identity constraint field"); + break; + } + + parseInfo->staticContext->error(QtXmlPatterns::tr("A construct was encountered " + "which is disallowed in the current language(%1).").arg(langName), ReportContext::XPST0003, fromYYLTYPE(sourceLocator, parseInfo)); @@ -1560,7 +1594,7 @@ Prolog: /* Empty. */ /* First part. */ | Prolog DefaultNamespaceDecl { - disallowedConstruct(parseInfo, @$); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$); if(parseInfo->hasSecondPrologPart) parseInfo->staticContext->error(QtXmlPatterns::tr("A default namespace declaration must occur before function, " "variable, and option declarations."), ReportContext::XPST0003, fromYYLTYPE(@$, parseInfo)); @@ -1579,7 +1613,7 @@ Prolog: /* Empty. */ } | Prolog Import { - disallowedConstruct(parseInfo, @$); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$); if(parseInfo->hasSecondPrologPart) parseInfo->staticContext->error(QtXmlPatterns::tr("Module imports must occur before function, " "variable, and option declarations."), ReportContext::XPST0003, fromYYLTYPE(@$, parseInfo)); @@ -1597,7 +1631,7 @@ Prolog: /* Empty. */ } | Prolog OptionDecl { - disallowedConstruct(parseInfo, @$); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$); parseInfo->hasSecondPrologPart = true; } @@ -1730,20 +1764,20 @@ TemplateName: NAME ElementName Setter: BoundarySpaceDecl /* [7] */ | DefaultCollationDecl { - disallowedConstruct(parseInfo, @$); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$); } | BaseURIDecl | ConstructionDecl { - disallowedConstruct(parseInfo, @$); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$); } | OrderingModeDecl { - disallowedConstruct(parseInfo, @$); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$); } | EmptyOrderDecl { - disallowedConstruct(parseInfo, @$); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$); } | CopyNamespacesDecl @@ -1755,7 +1789,7 @@ Separator: SEMI_COLON NamespaceDecl: DECLARE NAMESPACE NCNAME G_EQ URILiteral IsInternal Separator /* [10] */ { if(!$6) - disallowedConstruct(parseInfo, @$); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$); if($3 == QLatin1String("xmlns")) { @@ -1867,7 +1901,7 @@ OptionDecl: DECLARE OPTION ElementName StringLiteral Separator OrderingModeDecl: DECLARE ORDERING OrderingMode Separator /* [14] */ { - disallowedConstruct(parseInfo, @$); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$); if(parseInfo->hasDeclaration(ParserContext::OrderingModeDecl)) { parseInfo->staticContext->error(prologMessage("declare ordering"), @@ -1964,7 +1998,7 @@ DefaultCollationDecl: DECLARE DEFAULT COLLATION StringLiteral Separator BaseURIDecl: DECLARE BASEURI IsInternal URILiteral Separator /* [20] */ { - disallowedConstruct(parseInfo, @$, $3); + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XSLT20), parseInfo, @$, $3); if(parseInfo->hasDeclaration(ParserContext::BaseURIDecl)) { parseInfo->staticContext->error(prologMessage("declare base-uri"), @@ -2026,7 +2060,7 @@ FileLocation: URILiteral VarDecl: DECLARE VARIABLE IsInternal DOLLAR VarName TypeDeclaration VariableValue OptionalDefaultValue Separator /* [24] */ { - disallowedConstruct(parseInfo, @$, $3); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$, $3); if(variableByName($5, parseInfo)) { parseInfo->staticContext->error(QtXmlPatterns::tr("A variable by name %1 has already " @@ -2126,7 +2160,7 @@ FunctionDecl: DECLARE FUNCTION IsInternal FunctionName LPAREN ParamList RPAREN TypeDeclaration FunctionBody Separator /* [26] */ { if(!$3) - disallowedConstruct(parseInfo, @$, $3); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$, $3); /* If FunctionBody is null, it is 'external', otherwise the value is the body. */ const QXmlName::NamespaceCode ns($4.namespaceURI()); @@ -2696,7 +2730,7 @@ LetClause: LET IsInternal DOLLAR VarName TypeDeclaration ASSIGN ExprSingle } LetTail /* [36] */ { - disallowedConstruct(parseInfo, @$, $2); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$, $2); Q_ASSERT(parseInfo->variables.top()->name == $4); $$ = create(new LetClause($8, $9, parseInfo->variables.top()), @$, parseInfo); @@ -2835,6 +2869,7 @@ SomeQuantificationExpr: SOME DOLLAR VarName TypeDeclaration IN ExprSingle {$$ = parseInfo->staticContext->currentRangeSlot();} SomeQuantificationTail /* [X] */ { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = create(new QuantifiedExpression($8, QuantifiedExpression::Some, $6, $9), @$, parseInfo); parseInfo->finalizePushedVariable(); @@ -2863,6 +2898,7 @@ EveryQuantificationExpr: EVERY DOLLAR VarName TypeDeclaration IN ExprSingle {$$ = parseInfo->staticContext->currentRangeSlot();} EveryQuantificationTail /* [X] */ { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = create(new QuantifiedExpression($8, QuantifiedExpression::Every, $6, $9), @$, parseInfo); parseInfo->finalizePushedVariable(); @@ -2916,7 +2952,7 @@ TypeswitchExpr: TYPESWITCH LPAREN Expr RPAREN } CaseClause /* [43] */ { - disallowedConstruct(parseInfo, @$); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$); parseInfo->typeswitchSource.pop(); $$ = $6; } @@ -2976,18 +3012,21 @@ CaseDefault: DEFAULT RETURN ExprSingle IfExpr: IF LPAREN Expr RPAREN THEN ExprSingle ELSE ExprSingle /* [45] */ { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = create(new IfThenClause($3, $6, $8), @$, parseInfo); } OrExpr: AndExpr /* [46] */ | OrExpr OR AndExpr { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = create(new OrExpression($1, $3), @$, parseInfo); } AndExpr: ComparisonExpr /* [47] */ | AndExpr AND ComparisonExpr { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = create(new AndExpression($1, $3), @$, parseInfo); } @@ -2999,12 +3038,14 @@ ComparisonExpr: RangeExpr RangeExpr: AdditiveExpr /* [49] */ | AdditiveExpr TO AdditiveExpr { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = create(new RangeExpression($1, $3), @$, parseInfo); } AdditiveExpr: MultiplicativeExpr /* [50] */ | AdditiveExpr AdditiveOperator MultiplicativeExpr { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = create(new ArithmeticExpression($1, $2, $3), @$, parseInfo); } @@ -3014,6 +3055,7 @@ AdditiveOperator: PLUS {$$ = AtomicMathematician::Add;} MultiplicativeExpr: UnionExpr /* [51] */ | MultiplicativeExpr MultiplyOperator UnionExpr { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = create(new ArithmeticExpression($1, $2, $3), @$, parseInfo); } @@ -3025,12 +3067,18 @@ MultiplyOperator: STAR {$$ = AtomicMathematician::Multiply;} UnionExpr: IntersectExceptExpr /* [52] */ | UnionExpr UnionOperator IntersectExceptExpr { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 + | QXmlQuery::XPath20 + | QXmlQuery::XmlSchema11IdentityConstraintField + | QXmlQuery::XmlSchema11IdentityConstraintSelector), + parseInfo, @$); $$ = create(new CombineNodes($1, CombineNodes::Union, $3), @$, parseInfo); } IntersectExceptExpr: InstanceOfExpr /* [53] */ | IntersectExceptExpr IntersectOperator InstanceOfExpr { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = create(new CombineNodes($1, $2, $3), @$, parseInfo); } @@ -3049,31 +3097,36 @@ IntersectOperator: INTERSECT InstanceOfExpr: TreatExpr /* [54] */ | TreatExpr INSTANCE OF SequenceType { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = create(new InstanceOf($1, - SequenceType::Ptr($4)), @$, parseInfo); + SequenceType::Ptr($4)), @$, parseInfo); } TreatExpr: CastableExpr /* [55] */ | CastableExpr TREAT AS SequenceType { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = create(new TreatAs($1, $4), @$, parseInfo); } CastableExpr: CastExpr /* [56] */ | CastExpr CASTABLE AS SingleType { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = create(new CastableAs($1, $4), @$, parseInfo); } CastExpr: UnaryExpr /* [57] */ | UnaryExpr CAST AS SingleType { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = create(new CastAs($1, $4), @$, parseInfo); } UnaryExpr: ValueExpr /* [58] */ | UnaryOperator UnaryExpr { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = create(new UnaryExpression($1, $2, parseInfo->staticContext), @$, parseInfo); } @@ -3092,6 +3145,7 @@ ValueExpr: ValidateExpr GeneralComp: RangeExpr GeneralComparisonOperator RangeExpr /* [60] */ { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = create(new GeneralComparison($1, $2, $3, parseInfo->isBackwardsCompat.top()), @$, parseInfo); } @@ -3125,7 +3179,7 @@ NodeOperator: IS {$$ = QXmlNodeModelIndex::Is;} ValidateExpr: ValidationMode EnclosedExpr /* [63] */ { - disallowedConstruct(parseInfo, @$); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$); parseInfo->staticContext->error(QtXmlPatterns::tr("The Schema Validation Feature is not supported. " "Hence, %1-expressions may not be used.") .arg(formatKeyword("validate")), @@ -3143,6 +3197,7 @@ ValidationMode: VALIDATE {$$ = Validate::Strict;} ExtensionExpr: Pragmas EnclosedOptionalExpr /* [65] */ { + allowedIn(QXmlQuery::XQuery10, parseInfo, @$); /* We don't support any pragmas, so we only do the * necessary validation and use the fallback expression. */ @@ -3171,7 +3226,7 @@ Pragmas: Pragmas Pragma Pragma: PRAGMA_START PragmaName PragmaContents PRAGMA_END /* [66] */ { - disallowedConstruct(parseInfo, @$); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$); } PragmaContents: /* empty */ /* [67] */ @@ -3241,12 +3296,14 @@ StepExpr: FilteredAxisStep } | BASEURI StringLiteral CURLY_LBRACE Expr CURLY_RBRACE /* [X] */ { + allowedIn(QXmlQuery::XSLT20, parseInfo, @$); Q_ASSERT(!$2.isEmpty()); $$ = create(new StaticBaseURIStore($2, $4), @$, parseInfo); } | DECLARE NAMESPACE NCNAME G_EQ STRING_LITERAL CURLY_LBRACE /* [X] */ { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XSLT20), parseInfo, @$); parseInfo->resolvers.push(parseInfo->staticContext->namespaceBindings()); const NamespaceResolver::Ptr resolver(new DelegatingNamespaceResolver(parseInfo->staticContext->namespaceBindings())); resolver->addBinding(QXmlName(parseInfo->staticContext->namePool()->allocateNamespace($5), @@ -3449,6 +3506,36 @@ Axis: AxisToken COLONCOLON } else $$ = $1; + + switch($1) + { + case QXmlNodeModelIndex::AxisAttribute: + { + allowedIn(QueryLanguages( QXmlQuery::XPath20 + | QXmlQuery::XQuery10 + | QXmlQuery::XmlSchema11IdentityConstraintField + | QXmlQuery::XSLT20), + parseInfo, @$); + break; + } + case QXmlNodeModelIndex::AxisChild: + { + allowedIn(QueryLanguages( QXmlQuery::XPath20 + | QXmlQuery::XQuery10 + | QXmlQuery::XmlSchema11IdentityConstraintField + | QXmlQuery::XmlSchema11IdentityConstraintSelector + | QXmlQuery::XSLT20), + parseInfo, @$); + break; + } + default: + { + allowedIn(QueryLanguages( QXmlQuery::XPath20 + | QXmlQuery::XQuery10 + | QXmlQuery::XSLT20), + parseInfo, @$); + } + } } AxisToken: ANCESTOR_OR_SELF {$$ = QXmlNodeModelIndex::AxisAncestorOrSelf ;} @@ -3470,6 +3557,7 @@ AbbrevForwardStep: AT_SIGN } NodeTest /* [72] */ { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XSLT20 | QXmlQuery::XmlSchema11IdentityConstraintField), parseInfo, @$); $$ = create(new AxisStep(QXmlNodeModelIndex::AxisAttribute, $3), @$, parseInfo); parseInfo->restoreNodeTestSource(); @@ -3499,6 +3587,9 @@ AbbrevReverseStep: DOTDOT NodeTest: NameTest /* [78] */ | KindTest + { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); + } NameTest: ElementName /* [79] */ { @@ -3521,6 +3612,7 @@ WildCard: STAR } | ANY_PREFIX { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); const QXmlName::LocalNameCode c = parseInfo->staticContext->namePool()->allocateLocalName($1); $$ = LocalNameTest::create(parseInfo->nodeTestSource, c); } @@ -3528,6 +3620,7 @@ WildCard: STAR FilterExpr: PrimaryExpr /* [81] */ | FilterExpr LBRACKET Expr RBRACKET { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = create(GenericPredicate::create($1, $3, parseInfo->staticContext, fromYYLTYPE(@4, parseInfo)), @$, parseInfo); } @@ -3556,15 +3649,18 @@ Literal: NumericLiteral NumericLiteral: XPATH2_NUMBER /* [86] */ { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = createNumericLiteral($1, @$, parseInfo); } | NUMBER { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = createNumericLiteral($1, @$, parseInfo); } VarRef: DOLLAR VarName /* [87] */ { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = resolveVariable($2, @$, parseInfo, false); } @@ -3580,10 +3676,12 @@ VarName: NCNAME ParenthesizedExpr: LPAREN Expr RPAREN /* [89] */ { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = $2; } | LPAREN RPAREN { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); $$ = create(new EmptySequence, @$, parseInfo); } @@ -3599,6 +3697,7 @@ OrderingExpr: OrderingMode EnclosedExpr FunctionCallExpr: FunctionName LPAREN FunctionArguments RPAREN /* [93] */ { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); if(XPathHelper::isReservedNamespace($1.namespaceURI()) || $1.namespaceURI() == StandardNamespaces::InternalXSLT) { /* We got a call to a builtin function. */ const ReflectYYLTYPE ryy(@$, parseInfo); @@ -3641,9 +3740,12 @@ FunctionArguments: /* empty */ Constructor: DirectConstructor /* [94] */ { - disallowedConstruct(parseInfo, @$); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$); } | ComputedConstructor +/* The reason we cannot call alloweIn() as the action for ComputedConstructor, + * is that we use the computed constructors for XSL-T, and therefore generate + * INTERNAL tokens. */ DirectConstructor: DirElemConstructor /* [95] */ | DirCommentConstructor @@ -4075,7 +4177,7 @@ ComputedConstructor: CompDocConstructor CompDocConstructor: DOCUMENT IsInternal EnclosedExpr /* [110] */ { - disallowedConstruct(parseInfo, @$, $2); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$, $2); $$ = create(new DocumentConstructor($3), @$, parseInfo); } @@ -4088,7 +4190,7 @@ CompElemConstructor: ELEMENT IsInternal CompElementName EnclosedOptionalExpr /* [111] */ { Q_ASSERT(5); - disallowedConstruct(parseInfo, @$, $2); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$, $2); Expression::Ptr effExpr; @@ -4133,7 +4235,7 @@ CompAttrConstructor: ATTRIBUTE CompAttributeName EnclosedOptionalExpr /* [113] */ { - disallowedConstruct(parseInfo, @$, $2); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$, $2); const Expression::Ptr name(create(new AttributeNameValidator($3), @$, parseInfo)); @@ -4150,14 +4252,14 @@ CompTextConstructor: TEXT IsInternal EnclosedExpr CompCommentConstructor: COMMENT IsInternal EnclosedExpr /* [115] */ { - disallowedConstruct(parseInfo, @$, $2); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$, $2); $$ = create(new CommentConstructor(createSimpleContent($3, @$, parseInfo)), @$, parseInfo); } CompPIConstructor: PROCESSING_INSTRUCTION CompPIName EnclosedOptionalExpr /* [116] */ { - disallowedConstruct(parseInfo, @$, $2); + allowedIn(QXmlQuery::XQuery10, parseInfo, @$, $2); if($3) { @@ -4517,7 +4619,13 @@ PragmaName: NCNAME URILiteral: StringLiteral /* [140] */ StringLiteral: STRING_LITERAL /* [144] */ + { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); + } | XPATH2_STRING_LITERAL + { + allowedIn(QueryLanguages(QXmlQuery::XQuery10 | QXmlQuery::XPath20), parseInfo, @$); + } QName: QNAME /* [154] */ { diff --git a/src/xmlpatterns/schema/.gitignore b/src/xmlpatterns/schema/.gitignore new file mode 100644 index 0000000..2b29f27 --- /dev/null +++ b/src/xmlpatterns/schema/.gitignore @@ -0,0 +1 @@ +tests diff --git a/src/xmlpatterns/schema/builtinschemas.qrc b/src/xmlpatterns/schema/builtinschemas.qrc new file mode 100644 index 0000000..fb43d78 --- /dev/null +++ b/src/xmlpatterns/schema/builtinschemas.qrc @@ -0,0 +1,5 @@ + + + schemas/xml.xsd + + diff --git a/src/xmlpatterns/schema/doc/All_diagram.dot b/src/xmlpatterns/schema/doc/All_diagram.dot new file mode 100644 index 0000000..3352b723 --- /dev/null +++ b/src/xmlpatterns/schema/doc/All_diagram.dot @@ -0,0 +1,13 @@ +digraph All { + mindist = 2.0 + 1 -> 2 [label="annotation"] + 1 -> 3 [label="any"] + 1 -> 3 [label="element"] + 2 -> 3 [label="any"] + 2 -> 3 [label="element"] + 3 -> 3 [label="any"] + 3 -> 3 [label="element"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] + 3 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/Alternative_diagram.dot b/src/xmlpatterns/schema/doc/Alternative_diagram.dot new file mode 100644 index 0000000..2119c49 --- /dev/null +++ b/src/xmlpatterns/schema/doc/Alternative_diagram.dot @@ -0,0 +1,11 @@ +digraph Alternative { + mindist = 2.0 + 1 -> 3 [label="complexType"] + 1 -> 2 [label="annotation"] + 1 -> 3 [label="simpleType"] + 2 -> 3 [label="complexType"] + 2 -> 3 [label="simpleType"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] + 3 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/Annotation_diagram.dot b/src/xmlpatterns/schema/doc/Annotation_diagram.dot new file mode 100644 index 0000000..260b6f7 --- /dev/null +++ b/src/xmlpatterns/schema/doc/Annotation_diagram.dot @@ -0,0 +1,9 @@ +digraph Annotation { + mindist = 2.0 + 1 -> 2 [label="appinfo"] + 1 -> 2 [label="documentation"] + 2 -> 2 [label="appinfo"] + 2 -> 2 [label="documentation"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/AnyAttribute_diagram.dot b/src/xmlpatterns/schema/doc/AnyAttribute_diagram.dot new file mode 100644 index 0000000..d252ebd --- /dev/null +++ b/src/xmlpatterns/schema/doc/AnyAttribute_diagram.dot @@ -0,0 +1,6 @@ +digraph AnyAttribute { + mindist = 2.0 + 1 -> 2 [label="annotation"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/Any_diagram.dot b/src/xmlpatterns/schema/doc/Any_diagram.dot new file mode 100644 index 0000000..f54063f --- /dev/null +++ b/src/xmlpatterns/schema/doc/Any_diagram.dot @@ -0,0 +1,6 @@ +digraph Any { + mindist = 2.0 + 1 -> 2 [label="annotation"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/Assert_diagram.dot b/src/xmlpatterns/schema/doc/Assert_diagram.dot new file mode 100644 index 0000000..7093bef --- /dev/null +++ b/src/xmlpatterns/schema/doc/Assert_diagram.dot @@ -0,0 +1,6 @@ +digraph Assert { + mindist = 2.0 + 1 -> 2 [label="annotation"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/Choice_diagram.dot b/src/xmlpatterns/schema/doc/Choice_diagram.dot new file mode 100644 index 0000000..7b32016 --- /dev/null +++ b/src/xmlpatterns/schema/doc/Choice_diagram.dot @@ -0,0 +1,22 @@ +digraph Choice { + mindist = 2.0 + 1 -> 3 [label="choice"] + 1 -> 3 [label="group"] + 1 -> 2 [label="annotation"] + 1 -> 3 [label="sequence"] + 1 -> 3 [label="any"] + 1 -> 3 [label="element"] + 2 -> 3 [label="choice"] + 2 -> 3 [label="group"] + 2 -> 3 [label="sequence"] + 2 -> 3 [label="any"] + 2 -> 3 [label="element"] + 3 -> 3 [label="choice"] + 3 -> 3 [label="group"] + 3 -> 3 [label="sequence"] + 3 -> 3 [label="any"] + 3 -> 3 [label="element"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] + 3 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/ComplexContentExtension_diagram.dot b/src/xmlpatterns/schema/doc/ComplexContentExtension_diagram.dot new file mode 100644 index 0000000..6131612 --- /dev/null +++ b/src/xmlpatterns/schema/doc/ComplexContentExtension_diagram.dot @@ -0,0 +1,47 @@ +digraph ComplexContentExtension { + mindist = 2.0 + 1 -> 4 [label="choice"] + 1 -> 4 [label="group"] + 1 -> 4 [label="all"] + 1 -> 2 [label="annotation"] + 1 -> 4 [label="sequence"] + 1 -> 6 [label="anyAttribute"] + 1 -> 7 [label="assert"] + 1 -> 3 [label="openContent"] + 1 -> 5 [label="attribute"] + 1 -> 5 [label="attributeGroup"] + 2 -> 4 [label="choice"] + 2 -> 4 [label="group"] + 2 -> 4 [label="all"] + 2 -> 4 [label="sequence"] + 2 -> 6 [label="anyAttribute"] + 2 -> 7 [label="assert"] + 2 -> 3 [label="openContent"] + 2 -> 5 [label="attribute"] + 2 -> 5 [label="attributeGroup"] + 3 -> 4 [label="choice"] + 3 -> 4 [label="group"] + 3 -> 4 [label="all"] + 3 -> 4 [label="sequence"] + 3 -> 6 [label="anyAttribute"] + 3 -> 7 [label="assert"] + 3 -> 5 [label="attribute"] + 3 -> 5 [label="attributeGroup"] + 4 -> 6 [label="anyAttribute"] + 4 -> 7 [label="assert"] + 4 -> 5 [label="attribute"] + 4 -> 5 [label="attributeGroup"] + 5 -> 6 [label="anyAttribute"] + 5 -> 7 [label="assert"] + 5 -> 5 [label="attribute"] + 5 -> 5 [label="attributeGroup"] + 6 -> 7 [label="assert"] + 7 -> 7 [label="assert"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] + 3 [shape=doublecircle, style=filled, color=green] + 4 [shape=doublecircle, style=filled, color=green] + 5 [shape=doublecircle, style=filled, color=green] + 6 [shape=doublecircle, style=filled, color=green] + 7 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/ComplexContentRestriction_diagram.dot b/src/xmlpatterns/schema/doc/ComplexContentRestriction_diagram.dot new file mode 100644 index 0000000..bfda892 --- /dev/null +++ b/src/xmlpatterns/schema/doc/ComplexContentRestriction_diagram.dot @@ -0,0 +1,47 @@ +digraph ComplexContentRestriction { + mindist = 2.0 + 1 -> 4 [label="choice"] + 1 -> 4 [label="group"] + 1 -> 4 [label="all"] + 1 -> 2 [label="annotation"] + 1 -> 4 [label="sequence"] + 1 -> 6 [label="anyAttribute"] + 1 -> 7 [label="assert"] + 1 -> 3 [label="openContent"] + 1 -> 5 [label="attribute"] + 1 -> 5 [label="attributeGroup"] + 2 -> 4 [label="choice"] + 2 -> 4 [label="group"] + 2 -> 4 [label="all"] + 2 -> 4 [label="sequence"] + 2 -> 6 [label="anyAttribute"] + 2 -> 7 [label="assert"] + 2 -> 3 [label="openContent"] + 2 -> 5 [label="attribute"] + 2 -> 5 [label="attributeGroup"] + 3 -> 4 [label="choice"] + 3 -> 4 [label="group"] + 3 -> 4 [label="all"] + 3 -> 4 [label="sequence"] + 3 -> 6 [label="anyAttribute"] + 3 -> 7 [label="assert"] + 3 -> 5 [label="attribute"] + 3 -> 5 [label="attributeGroup"] + 4 -> 6 [label="anyAttribute"] + 4 -> 7 [label="assert"] + 4 -> 5 [label="attribute"] + 4 -> 5 [label="attributeGroup"] + 5 -> 6 [label="anyAttribute"] + 5 -> 7 [label="assert"] + 5 -> 5 [label="attribute"] + 5 -> 5 [label="attributeGroup"] + 6 -> 7 [label="assert"] + 7 -> 7 [label="assert"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] + 3 [shape=doublecircle, style=filled, color=green] + 4 [shape=doublecircle, style=filled, color=green] + 5 [shape=doublecircle, style=filled, color=green] + 6 [shape=doublecircle, style=filled, color=green] + 7 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/ComplexContent_diagram.dot b/src/xmlpatterns/schema/doc/ComplexContent_diagram.dot new file mode 100644 index 0000000..949c27e --- /dev/null +++ b/src/xmlpatterns/schema/doc/ComplexContent_diagram.dot @@ -0,0 +1,11 @@ +digraph ComplexContent { + mindist = 2.0 + 1 -> 3 [label="restriction"] + 1 -> 2 [label="annotation"] + 1 -> 3 [label="extension"] + 2 -> 3 [label="restriction"] + 2 -> 3 [label="extension"] + 1 [shape=circle, style=filled, color=blue] + 2 [shape=circle, style=filled, color=red] + 3 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/DefaultOpenContent_diagram.dot b/src/xmlpatterns/schema/doc/DefaultOpenContent_diagram.dot new file mode 100644 index 0000000..61e7d14 --- /dev/null +++ b/src/xmlpatterns/schema/doc/DefaultOpenContent_diagram.dot @@ -0,0 +1,9 @@ +digraph DefaultOpenContent { + mindist = 2.0 + 1 -> 2 [label="annotation"] + 1 -> 3 [label="any"] + 2 -> 3 [label="any"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=circle, style=filled, color=red] + 3 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/EnumerationFacet_diagram.dot b/src/xmlpatterns/schema/doc/EnumerationFacet_diagram.dot new file mode 100644 index 0000000..91be76b --- /dev/null +++ b/src/xmlpatterns/schema/doc/EnumerationFacet_diagram.dot @@ -0,0 +1,6 @@ +digraph EnumerationFacet { + mindist = 2.0 + 1 -> 2 [label="annotation"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/Field_diagram.dot b/src/xmlpatterns/schema/doc/Field_diagram.dot new file mode 100644 index 0000000..1c597b3 --- /dev/null +++ b/src/xmlpatterns/schema/doc/Field_diagram.dot @@ -0,0 +1,6 @@ +digraph Field { + mindist = 2.0 + 1 -> 2 [label="annotation"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/FractionDigitsFacet_diagram.dot b/src/xmlpatterns/schema/doc/FractionDigitsFacet_diagram.dot new file mode 100644 index 0000000..5e098b3 --- /dev/null +++ b/src/xmlpatterns/schema/doc/FractionDigitsFacet_diagram.dot @@ -0,0 +1,6 @@ +digraph FractionDigitsFacet { + mindist = 2.0 + 1 -> 2 [label="annotation"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/GlobalAttribute_diagram.dot b/src/xmlpatterns/schema/doc/GlobalAttribute_diagram.dot new file mode 100644 index 0000000..25a1a43 --- /dev/null +++ b/src/xmlpatterns/schema/doc/GlobalAttribute_diagram.dot @@ -0,0 +1,9 @@ +digraph GlobalAttribute { + mindist = 2.0 + 1 -> 2 [label="annotation"] + 1 -> 3 [label="simpleType"] + 2 -> 3 [label="simpleType"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] + 3 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/GlobalComplexType_diagram.dot b/src/xmlpatterns/schema/doc/GlobalComplexType_diagram.dot new file mode 100644 index 0000000..05e40b7 --- /dev/null +++ b/src/xmlpatterns/schema/doc/GlobalComplexType_diagram.dot @@ -0,0 +1,52 @@ +digraph GlobalComplexType { + mindist = 2.0 + 1 -> 5 [label="choice"] + 1 -> 3 [label="complexContent"] + 1 -> 5 [label="group"] + 1 -> 5 [label="all"] + 1 -> 2 [label="annotation"] + 1 -> 5 [label="sequence"] + 1 -> 3 [label="simpleContent"] + 1 -> 7 [label="anyAttribute"] + 1 -> 8 [label="assert"] + 1 -> 4 [label="openContent"] + 1 -> 6 [label="attribute"] + 1 -> 6 [label="attributeGroup"] + 2 -> 5 [label="choice"] + 2 -> 3 [label="complexContent"] + 2 -> 5 [label="group"] + 2 -> 5 [label="all"] + 2 -> 5 [label="sequence"] + 2 -> 3 [label="simpleContent"] + 2 -> 7 [label="anyAttribute"] + 2 -> 8 [label="assert"] + 2 -> 4 [label="openContent"] + 2 -> 6 [label="attribute"] + 2 -> 6 [label="attributeGroup"] + 4 -> 5 [label="choice"] + 4 -> 5 [label="group"] + 4 -> 5 [label="all"] + 4 -> 5 [label="sequence"] + 4 -> 7 [label="anyAttribute"] + 4 -> 8 [label="assert"] + 4 -> 6 [label="attribute"] + 4 -> 6 [label="attributeGroup"] + 5 -> 7 [label="anyAttribute"] + 5 -> 8 [label="assert"] + 5 -> 6 [label="attribute"] + 5 -> 6 [label="attributeGroup"] + 6 -> 7 [label="anyAttribute"] + 6 -> 8 [label="assert"] + 6 -> 6 [label="attribute"] + 6 -> 6 [label="attributeGroup"] + 7 -> 8 [label="assert"] + 8 -> 8 [label="assert"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] + 3 [shape=doublecircle, style=filled, color=green] + 4 [shape=doublecircle, style=filled, color=green] + 5 [shape=doublecircle, style=filled, color=green] + 6 [shape=doublecircle, style=filled, color=green] + 7 [shape=doublecircle, style=filled, color=green] + 8 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/GlobalElement_diagram.dot b/src/xmlpatterns/schema/doc/GlobalElement_diagram.dot new file mode 100644 index 0000000..20447a7 --- /dev/null +++ b/src/xmlpatterns/schema/doc/GlobalElement_diagram.dot @@ -0,0 +1,32 @@ +digraph GlobalElement { + mindist = 2.0 + 1 -> 3 [label="complexType"] + 1 -> 4 [label="alternative"] + 1 -> 2 [label="annotation"] + 1 -> 5 [label="key"] + 1 -> 3 [label="simpleType"] + 1 -> 5 [label="keyref"] + 1 -> 5 [label="unique"] + 2 -> 3 [label="complexType"] + 2 -> 4 [label="alternative"] + 2 -> 5 [label="key"] + 2 -> 3 [label="simpleType"] + 2 -> 5 [label="keyref"] + 2 -> 5 [label="unique"] + 3 -> 4 [label="alternative"] + 3 -> 5 [label="key"] + 3 -> 5 [label="keyref"] + 3 -> 5 [label="unique"] + 4 -> 4 [label="alternative"] + 4 -> 5 [label="key"] + 4 -> 5 [label="keyref"] + 4 -> 5 [label="unique"] + 5 -> 5 [label="key"] + 5 -> 5 [label="keyref"] + 5 -> 5 [label="unique"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] + 3 [shape=doublecircle, style=filled, color=green] + 4 [shape=doublecircle, style=filled, color=green] + 5 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/GlobalSimpleType_diagram.dot b/src/xmlpatterns/schema/doc/GlobalSimpleType_diagram.dot new file mode 100644 index 0000000..ccb7f54 --- /dev/null +++ b/src/xmlpatterns/schema/doc/GlobalSimpleType_diagram.dot @@ -0,0 +1,13 @@ +digraph GlobalSimpleType { + mindist = 2.0 + 1 -> 3 [label="restriction"] + 1 -> 2 [label="annotation"] + 1 -> 3 [label="list"] + 1 -> 3 [label="union"] + 2 -> 3 [label="restriction"] + 2 -> 3 [label="list"] + 2 -> 3 [label="union"] + 1 [shape=circle, style=filled, color=blue] + 2 [shape=circle, style=filled, color=red] + 3 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/Import_diagram.dot b/src/xmlpatterns/schema/doc/Import_diagram.dot new file mode 100644 index 0000000..3484bc3 --- /dev/null +++ b/src/xmlpatterns/schema/doc/Import_diagram.dot @@ -0,0 +1,6 @@ +digraph Import { + mindist = 2.0 + 1 -> 2 [label="annotation"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/Include_diagram.dot b/src/xmlpatterns/schema/doc/Include_diagram.dot new file mode 100644 index 0000000..357e4c9 --- /dev/null +++ b/src/xmlpatterns/schema/doc/Include_diagram.dot @@ -0,0 +1,6 @@ +digraph Include { + mindist = 2.0 + 1 -> 2 [label="annotation"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/KeyRef_diagram.dot b/src/xmlpatterns/schema/doc/KeyRef_diagram.dot new file mode 100644 index 0000000..ff425b9 --- /dev/null +++ b/src/xmlpatterns/schema/doc/KeyRef_diagram.dot @@ -0,0 +1,12 @@ +digraph KeyRef { + mindist = 2.0 + 1 -> 2 [label="annotation"] + 1 -> 3 [label="selector"] + 2 -> 3 [label="selector"] + 3 -> 4 [label="field"] + 4 -> 4 [label="field"] + 1 [shape=circle, style=filled, color=blue] + 2 [shape=circle, style=filled, color=red] + 3 [shape=circle, style=filled, color=red] + 4 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/Key_diagram.dot b/src/xmlpatterns/schema/doc/Key_diagram.dot new file mode 100644 index 0000000..bbc09cd --- /dev/null +++ b/src/xmlpatterns/schema/doc/Key_diagram.dot @@ -0,0 +1,12 @@ +digraph Key { + mindist = 2.0 + 1 -> 2 [label="annotation"] + 1 -> 3 [label="selector"] + 2 -> 3 [label="selector"] + 3 -> 4 [label="field"] + 4 -> 4 [label="field"] + 1 [shape=circle, style=filled, color=blue] + 2 [shape=circle, style=filled, color=red] + 3 [shape=circle, style=filled, color=red] + 4 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/LengthFacet_diagram.dot b/src/xmlpatterns/schema/doc/LengthFacet_diagram.dot new file mode 100644 index 0000000..1f9205b --- /dev/null +++ b/src/xmlpatterns/schema/doc/LengthFacet_diagram.dot @@ -0,0 +1,6 @@ +digraph LengthFacet { + mindist = 2.0 + 1 -> 2 [label="annotation"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/List_diagram.dot b/src/xmlpatterns/schema/doc/List_diagram.dot new file mode 100644 index 0000000..44cc698 --- /dev/null +++ b/src/xmlpatterns/schema/doc/List_diagram.dot @@ -0,0 +1,9 @@ +digraph List { + mindist = 2.0 + 1 -> 2 [label="annotation"] + 1 -> 3 [label="simpleType"] + 2 -> 3 [label="simpleType"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] + 3 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/LocalAll_diagram.dot b/src/xmlpatterns/schema/doc/LocalAll_diagram.dot new file mode 100644 index 0000000..88f1b61 --- /dev/null +++ b/src/xmlpatterns/schema/doc/LocalAll_diagram.dot @@ -0,0 +1,13 @@ +digraph LocalAll { + mindist = 2.0 + 1 -> 2 [label="annotation"] + 1 -> 3 [label="any"] + 1 -> 3 [label="element"] + 2 -> 3 [label="any"] + 2 -> 3 [label="element"] + 3 -> 3 [label="any"] + 3 -> 3 [label="element"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] + 3 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/LocalAttribute_diagram.dot b/src/xmlpatterns/schema/doc/LocalAttribute_diagram.dot new file mode 100644 index 0000000..b01f0cf --- /dev/null +++ b/src/xmlpatterns/schema/doc/LocalAttribute_diagram.dot @@ -0,0 +1,9 @@ +digraph LocalAttribute { + mindist = 2.0 + 1 -> 2 [label="annotation"] + 1 -> 3 [label="simpleType"] + 2 -> 3 [label="simpleType"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] + 3 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/LocalChoice_diagram.dot b/src/xmlpatterns/schema/doc/LocalChoice_diagram.dot new file mode 100644 index 0000000..b16c47f --- /dev/null +++ b/src/xmlpatterns/schema/doc/LocalChoice_diagram.dot @@ -0,0 +1,22 @@ +digraph LocalChoice { + mindist = 2.0 + 1 -> 3 [label="choice"] + 1 -> 3 [label="group"] + 1 -> 2 [label="annotation"] + 1 -> 3 [label="sequence"] + 1 -> 3 [label="any"] + 1 -> 3 [label="element"] + 2 -> 3 [label="choice"] + 2 -> 3 [label="group"] + 2 -> 3 [label="sequence"] + 2 -> 3 [label="any"] + 2 -> 3 [label="element"] + 3 -> 3 [label="choice"] + 3 -> 3 [label="group"] + 3 -> 3 [label="sequence"] + 3 -> 3 [label="any"] + 3 -> 3 [label="element"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] + 3 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/LocalComplexType_diagram.dot b/src/xmlpatterns/schema/doc/LocalComplexType_diagram.dot new file mode 100644 index 0000000..92c54b7 --- /dev/null +++ b/src/xmlpatterns/schema/doc/LocalComplexType_diagram.dot @@ -0,0 +1,52 @@ +digraph LocalComplexType { + mindist = 2.0 + 1 -> 5 [label="choice"] + 1 -> 3 [label="complexContent"] + 1 -> 5 [label="group"] + 1 -> 5 [label="all"] + 1 -> 2 [label="annotation"] + 1 -> 5 [label="sequence"] + 1 -> 3 [label="simpleContent"] + 1 -> 7 [label="anyAttribute"] + 1 -> 8 [label="assert"] + 1 -> 4 [label="openContent"] + 1 -> 6 [label="attribute"] + 1 -> 6 [label="attributeGroup"] + 2 -> 5 [label="choice"] + 2 -> 3 [label="complexContent"] + 2 -> 5 [label="group"] + 2 -> 5 [label="all"] + 2 -> 5 [label="sequence"] + 2 -> 3 [label="simpleContent"] + 2 -> 7 [label="anyAttribute"] + 2 -> 8 [label="assert"] + 2 -> 4 [label="openContent"] + 2 -> 6 [label="attribute"] + 2 -> 6 [label="attributeGroup"] + 4 -> 5 [label="choice"] + 4 -> 5 [label="group"] + 4 -> 5 [label="all"] + 4 -> 5 [label="sequence"] + 4 -> 7 [label="anyAttribute"] + 4 -> 8 [label="assert"] + 4 -> 6 [label="attribute"] + 4 -> 6 [label="attributeGroup"] + 5 -> 7 [label="anyAttribute"] + 5 -> 8 [label="assert"] + 5 -> 6 [label="attribute"] + 5 -> 6 [label="attributeGroup"] + 6 -> 7 [label="anyAttribute"] + 6 -> 8 [label="assert"] + 6 -> 6 [label="attribute"] + 6 -> 6 [label="attributeGroup"] + 7 -> 8 [label="assert"] + 8 -> 8 [label="assert"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] + 3 [shape=doublecircle, style=filled, color=green] + 4 [shape=doublecircle, style=filled, color=green] + 5 [shape=doublecircle, style=filled, color=green] + 6 [shape=doublecircle, style=filled, color=green] + 7 [shape=doublecircle, style=filled, color=green] + 8 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/LocalElement_diagram.dot b/src/xmlpatterns/schema/doc/LocalElement_diagram.dot new file mode 100644 index 0000000..397397a --- /dev/null +++ b/src/xmlpatterns/schema/doc/LocalElement_diagram.dot @@ -0,0 +1,32 @@ +digraph LocalElement { + mindist = 2.0 + 1 -> 3 [label="complexType"] + 1 -> 4 [label="alternative"] + 1 -> 2 [label="annotation"] + 1 -> 5 [label="key"] + 1 -> 3 [label="simpleType"] + 1 -> 5 [label="keyref"] + 1 -> 5 [label="unique"] + 2 -> 3 [label="complexType"] + 2 -> 4 [label="alternative"] + 2 -> 5 [label="key"] + 2 -> 3 [label="simpleType"] + 2 -> 5 [label="keyref"] + 2 -> 5 [label="unique"] + 3 -> 4 [label="alternative"] + 3 -> 5 [label="key"] + 3 -> 5 [label="keyref"] + 3 -> 5 [label="unique"] + 4 -> 4 [label="alternative"] + 4 -> 5 [label="key"] + 4 -> 5 [label="keyref"] + 4 -> 5 [label="unique"] + 5 -> 5 [label="key"] + 5 -> 5 [label="keyref"] + 5 -> 5 [label="unique"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] + 3 [shape=doublecircle, style=filled, color=green] + 4 [shape=doublecircle, style=filled, color=green] + 5 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/LocalSequence_diagram.dot b/src/xmlpatterns/schema/doc/LocalSequence_diagram.dot new file mode 100644 index 0000000..0dc7f39 --- /dev/null +++ b/src/xmlpatterns/schema/doc/LocalSequence_diagram.dot @@ -0,0 +1,22 @@ +digraph LocalSequence { + mindist = 2.0 + 1 -> 3 [label="choice"] + 1 -> 3 [label="group"] + 1 -> 2 [label="annotation"] + 1 -> 3 [label="sequence"] + 1 -> 3 [label="any"] + 1 -> 3 [label="element"] + 2 -> 3 [label="choice"] + 2 -> 3 [label="group"] + 2 -> 3 [label="sequence"] + 2 -> 3 [label="any"] + 2 -> 3 [label="element"] + 3 -> 3 [label="choice"] + 3 -> 3 [label="group"] + 3 -> 3 [label="sequence"] + 3 -> 3 [label="any"] + 3 -> 3 [label="element"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] + 3 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/LocalSimpleType_diagram.dot b/src/xmlpatterns/schema/doc/LocalSimpleType_diagram.dot new file mode 100644 index 0000000..ac13305 --- /dev/null +++ b/src/xmlpatterns/schema/doc/LocalSimpleType_diagram.dot @@ -0,0 +1,13 @@ +digraph LocalSimpleType { + mindist = 2.0 + 1 -> 3 [label="restriction"] + 1 -> 2 [label="annotation"] + 1 -> 3 [label="list"] + 1 -> 3 [label="union"] + 2 -> 3 [label="restriction"] + 2 -> 3 [label="list"] + 2 -> 3 [label="union"] + 1 [shape=circle, style=filled, color=blue] + 2 [shape=circle, style=filled, color=red] + 3 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/MaxExclusiveFacet_diagram.dot b/src/xmlpatterns/schema/doc/MaxExclusiveFacet_diagram.dot new file mode 100644 index 0000000..28364f7 --- /dev/null +++ b/src/xmlpatterns/schema/doc/MaxExclusiveFacet_diagram.dot @@ -0,0 +1,6 @@ +digraph MaxExclusiveFacet { + mindist = 2.0 + 1 -> 2 [label="annotation"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/MaxInclusiveFacet_diagram.dot b/src/xmlpatterns/schema/doc/MaxInclusiveFacet_diagram.dot new file mode 100644 index 0000000..9e2c265 --- /dev/null +++ b/src/xmlpatterns/schema/doc/MaxInclusiveFacet_diagram.dot @@ -0,0 +1,6 @@ +digraph MaxInclusiveFacet { + mindist = 2.0 + 1 -> 2 [label="annotation"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/MaxLengthFacet_diagram.dot b/src/xmlpatterns/schema/doc/MaxLengthFacet_diagram.dot new file mode 100644 index 0000000..d565217 --- /dev/null +++ b/src/xmlpatterns/schema/doc/MaxLengthFacet_diagram.dot @@ -0,0 +1,6 @@ +digraph MaxLengthFacet { + mindist = 2.0 + 1 -> 2 [label="annotation"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/MinExclusiveFacet_diagram.dot b/src/xmlpatterns/schema/doc/MinExclusiveFacet_diagram.dot new file mode 100644 index 0000000..d3b3f1f --- /dev/null +++ b/src/xmlpatterns/schema/doc/MinExclusiveFacet_diagram.dot @@ -0,0 +1,6 @@ +digraph MinExclusiveFacet { + mindist = 2.0 + 1 -> 2 [label="annotation"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/MinInclusiveFacet_diagram.dot b/src/xmlpatterns/schema/doc/MinInclusiveFacet_diagram.dot new file mode 100644 index 0000000..e5ca65d --- /dev/null +++ b/src/xmlpatterns/schema/doc/MinInclusiveFacet_diagram.dot @@ -0,0 +1,6 @@ +digraph MinInclusiveFacet { + mindist = 2.0 + 1 -> 2 [label="annotation"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/MinLengthFacet_diagram.dot b/src/xmlpatterns/schema/doc/MinLengthFacet_diagram.dot new file mode 100644 index 0000000..1dcced4 --- /dev/null +++ b/src/xmlpatterns/schema/doc/MinLengthFacet_diagram.dot @@ -0,0 +1,6 @@ +digraph MinLengthFacet { + mindist = 2.0 + 1 -> 2 [label="annotation"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/NamedAttributeGroup_diagram.dot b/src/xmlpatterns/schema/doc/NamedAttributeGroup_diagram.dot new file mode 100644 index 0000000..1754f67 --- /dev/null +++ b/src/xmlpatterns/schema/doc/NamedAttributeGroup_diagram.dot @@ -0,0 +1,17 @@ +digraph NamedAttributeGroup { + mindist = 2.0 + 1 -> 2 [label="annotation"] + 1 -> 4 [label="anyAttribute"] + 1 -> 3 [label="attribute"] + 1 -> 3 [label="attributeGroup"] + 2 -> 4 [label="anyAttribute"] + 2 -> 3 [label="attribute"] + 2 -> 3 [label="attributeGroup"] + 3 -> 4 [label="anyAttribute"] + 3 -> 3 [label="attribute"] + 3 -> 3 [label="attributeGroup"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] + 3 [shape=doublecircle, style=filled, color=green] + 4 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/NamedGroup_diagram.dot b/src/xmlpatterns/schema/doc/NamedGroup_diagram.dot new file mode 100644 index 0000000..6d9a289 --- /dev/null +++ b/src/xmlpatterns/schema/doc/NamedGroup_diagram.dot @@ -0,0 +1,13 @@ +digraph NamedGroup { + mindist = 2.0 + 1 -> 3 [label="choice"] + 1 -> 3 [label="all"] + 1 -> 2 [label="annotation"] + 1 -> 3 [label="sequence"] + 2 -> 3 [label="choice"] + 2 -> 3 [label="all"] + 2 -> 3 [label="sequence"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] + 3 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/Notation_diagram.dot b/src/xmlpatterns/schema/doc/Notation_diagram.dot new file mode 100644 index 0000000..951f26a --- /dev/null +++ b/src/xmlpatterns/schema/doc/Notation_diagram.dot @@ -0,0 +1,6 @@ +digraph Notation { + mindist = 2.0 + 1 -> 2 [label="annotation"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/Override_diagram.dot b/src/xmlpatterns/schema/doc/Override_diagram.dot new file mode 100644 index 0000000..448451a --- /dev/null +++ b/src/xmlpatterns/schema/doc/Override_diagram.dot @@ -0,0 +1,21 @@ +digraph Override { + mindist = 2.0 + 1 -> 2 [label="group"] + 1 -> 2 [label="complexType"] + 1 -> 2 [label="annotation"] + 1 -> 2 [label="simpleType"] + 1 -> 2 [label="element"] + 1 -> 2 [label="notation"] + 1 -> 2 [label="attribute"] + 1 -> 2 [label="attributeGroup"] + 2 -> 2 [label="group"] + 2 -> 2 [label="complexType"] + 2 -> 2 [label="annotation"] + 2 -> 2 [label="simpleType"] + 2 -> 2 [label="element"] + 2 -> 2 [label="notation"] + 2 -> 2 [label="attribute"] + 2 -> 2 [label="attributeGroup"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/PatternFacet_diagram.dot b/src/xmlpatterns/schema/doc/PatternFacet_diagram.dot new file mode 100644 index 0000000..794d74c --- /dev/null +++ b/src/xmlpatterns/schema/doc/PatternFacet_diagram.dot @@ -0,0 +1,6 @@ +digraph PatternFacet { + mindist = 2.0 + 1 -> 2 [label="annotation"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/Redefine_diagram.dot b/src/xmlpatterns/schema/doc/Redefine_diagram.dot new file mode 100644 index 0000000..ba4871d --- /dev/null +++ b/src/xmlpatterns/schema/doc/Redefine_diagram.dot @@ -0,0 +1,15 @@ +digraph Redefine { + mindist = 2.0 + 1 -> 2 [label="group"] + 1 -> 2 [label="complexType"] + 1 -> 2 [label="annotation"] + 1 -> 2 [label="simpleType"] + 1 -> 2 [label="attributeGroup"] + 2 -> 2 [label="group"] + 2 -> 2 [label="complexType"] + 2 -> 2 [label="annotation"] + 2 -> 2 [label="simpleType"] + 2 -> 2 [label="attributeGroup"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/ReferredAttributeGroup_diagram.dot b/src/xmlpatterns/schema/doc/ReferredAttributeGroup_diagram.dot new file mode 100644 index 0000000..fd08872 --- /dev/null +++ b/src/xmlpatterns/schema/doc/ReferredAttributeGroup_diagram.dot @@ -0,0 +1,6 @@ +digraph ReferredAttributeGroup { + mindist = 2.0 + 1 -> 2 [label="annotation"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/ReferredGroup_diagram.dot b/src/xmlpatterns/schema/doc/ReferredGroup_diagram.dot new file mode 100644 index 0000000..c32f69f --- /dev/null +++ b/src/xmlpatterns/schema/doc/ReferredGroup_diagram.dot @@ -0,0 +1,13 @@ +digraph ReferredGroup { + mindist = 2.0 + 1 -> 3 [label="choice"] + 1 -> 3 [label="all"] + 1 -> 2 [label="annotation"] + 1 -> 3 [label="sequence"] + 2 -> 3 [label="choice"] + 2 -> 3 [label="all"] + 2 -> 3 [label="sequence"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] + 3 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/Schema_diagram.dot b/src/xmlpatterns/schema/doc/Schema_diagram.dot new file mode 100644 index 0000000..7d39337 --- /dev/null +++ b/src/xmlpatterns/schema/doc/Schema_diagram.dot @@ -0,0 +1,66 @@ +digraph Schema { + mindist = 2.0 + 1 -> 5 [label="group"] + 1 -> 5 [label="complexType"] + 1 -> 2 [label="import"] + 1 -> 2 [label="include"] + 1 -> 2 [label="annotation"] + 1 -> 3 [label="defaultOpenContent"] + 1 -> 5 [label="simpleType"] + 1 -> 5 [label="element"] + 1 -> 5 [label="notation"] + 1 -> 2 [label="override"] + 1 -> 5 [label="attribute"] + 1 -> 5 [label="attributeGroup"] + 1 -> 2 [label="redefine"] + 2 -> 5 [label="group"] + 2 -> 5 [label="complexType"] + 2 -> 2 [label="import"] + 2 -> 2 [label="include"] + 2 -> 2 [label="annotation"] + 2 -> 3 [label="defaultOpenContent"] + 2 -> 5 [label="simpleType"] + 2 -> 5 [label="element"] + 2 -> 5 [label="notation"] + 2 -> 2 [label="override"] + 2 -> 5 [label="attribute"] + 2 -> 5 [label="attributeGroup"] + 2 -> 2 [label="redefine"] + 3 -> 5 [label="group"] + 3 -> 5 [label="complexType"] + 3 -> 4 [label="annotation"] + 3 -> 5 [label="simpleType"] + 3 -> 5 [label="element"] + 3 -> 5 [label="notation"] + 3 -> 5 [label="attribute"] + 3 -> 5 [label="attributeGroup"] + 4 -> 5 [label="group"] + 4 -> 5 [label="complexType"] + 4 -> 5 [label="simpleType"] + 4 -> 5 [label="element"] + 4 -> 5 [label="notation"] + 4 -> 5 [label="attribute"] + 4 -> 5 [label="attributeGroup"] + 5 -> 5 [label="group"] + 5 -> 5 [label="complexType"] + 5 -> 6 [label="annotation"] + 5 -> 5 [label="simpleType"] + 5 -> 5 [label="element"] + 5 -> 5 [label="notation"] + 5 -> 5 [label="attribute"] + 5 -> 5 [label="attributeGroup"] + 6 -> 5 [label="group"] + 6 -> 5 [label="complexType"] + 6 -> 6 [label="annotation"] + 6 -> 5 [label="simpleType"] + 6 -> 5 [label="element"] + 6 -> 5 [label="notation"] + 6 -> 5 [label="attribute"] + 6 -> 5 [label="attributeGroup"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] + 3 [shape=doublecircle, style=filled, color=green] + 4 [shape=doublecircle, style=filled, color=green] + 5 [shape=doublecircle, style=filled, color=green] + 6 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/Selector_diagram.dot b/src/xmlpatterns/schema/doc/Selector_diagram.dot new file mode 100644 index 0000000..f3e93dc --- /dev/null +++ b/src/xmlpatterns/schema/doc/Selector_diagram.dot @@ -0,0 +1,6 @@ +digraph Selector { + mindist = 2.0 + 1 -> 2 [label="annotation"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/Sequence_diagram.dot b/src/xmlpatterns/schema/doc/Sequence_diagram.dot new file mode 100644 index 0000000..9172744 --- /dev/null +++ b/src/xmlpatterns/schema/doc/Sequence_diagram.dot @@ -0,0 +1,22 @@ +digraph Sequence { + mindist = 2.0 + 1 -> 3 [label="choice"] + 1 -> 3 [label="group"] + 1 -> 2 [label="annotation"] + 1 -> 3 [label="sequence"] + 1 -> 3 [label="any"] + 1 -> 3 [label="element"] + 2 -> 3 [label="choice"] + 2 -> 3 [label="group"] + 2 -> 3 [label="sequence"] + 2 -> 3 [label="any"] + 2 -> 3 [label="element"] + 3 -> 3 [label="choice"] + 3 -> 3 [label="group"] + 3 -> 3 [label="sequence"] + 3 -> 3 [label="any"] + 3 -> 3 [label="element"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] + 3 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/SimpleContentExtension_diagram.dot b/src/xmlpatterns/schema/doc/SimpleContentExtension_diagram.dot new file mode 100644 index 0000000..3ceebfd --- /dev/null +++ b/src/xmlpatterns/schema/doc/SimpleContentExtension_diagram.dot @@ -0,0 +1,23 @@ +digraph SimpleContentExtension { + mindist = 2.0 + 1 -> 2 [label="annotation"] + 1 -> 4 [label="anyAttribute"] + 1 -> 5 [label="assert"] + 1 -> 3 [label="attribute"] + 1 -> 3 [label="attributeGroup"] + 2 -> 4 [label="anyAttribute"] + 2 -> 5 [label="assert"] + 2 -> 3 [label="attribute"] + 2 -> 3 [label="attributeGroup"] + 3 -> 4 [label="anyAttribute"] + 3 -> 5 [label="assert"] + 3 -> 3 [label="attribute"] + 3 -> 3 [label="attributeGroup"] + 4 -> 5 [label="assert"] + 5 -> 5 [label="assert"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] + 3 [shape=doublecircle, style=filled, color=green] + 4 [shape=doublecircle, style=filled, color=green] + 5 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/SimpleContentRestriction_diagram.dot b/src/xmlpatterns/schema/doc/SimpleContentRestriction_diagram.dot new file mode 100644 index 0000000..75b0b71 --- /dev/null +++ b/src/xmlpatterns/schema/doc/SimpleContentRestriction_diagram.dot @@ -0,0 +1,87 @@ +digraph SimpleContentRestriction { + mindist = 2.0 + 1 -> 3 [label="simpleType"] + 1 -> 2 [label="annotation"] + 1 -> 4 [label="length"] + 1 -> 6 [label="anyAttribute"] + 1 -> 4 [label="maxExclusive"] + 1 -> 4 [label="totalDigits"] + 1 -> 4 [label="maxInclusive"] + 1 -> 4 [label="maxLength"] + 1 -> 7 [label="assert"] + 1 -> 4 [label="assertion"] + 1 -> 5 [label="attribute"] + 1 -> 4 [label="minExclusive"] + 1 -> 5 [label="attributeGroup"] + 1 -> 4 [label="minInclusive"] + 1 -> 4 [label="minLength"] + 1 -> 4 [label="whiteSpace"] + 1 -> 4 [label="pattern"] + 1 -> 4 [label="enumeration"] + 1 -> 4 [label="fractionDigits"] + 2 -> 3 [label="simpleType"] + 2 -> 4 [label="length"] + 2 -> 6 [label="anyAttribute"] + 2 -> 4 [label="maxExclusive"] + 2 -> 4 [label="totalDigits"] + 2 -> 4 [label="maxInclusive"] + 2 -> 4 [label="maxLength"] + 2 -> 7 [label="assert"] + 2 -> 4 [label="assertion"] + 2 -> 5 [label="attribute"] + 2 -> 4 [label="minExclusive"] + 2 -> 5 [label="attributeGroup"] + 2 -> 4 [label="minInclusive"] + 2 -> 4 [label="minLength"] + 2 -> 4 [label="whiteSpace"] + 2 -> 4 [label="pattern"] + 2 -> 4 [label="enumeration"] + 2 -> 4 [label="fractionDigits"] + 3 -> 4 [label="fractionDigits"] + 3 -> 4 [label="minLength"] + 3 -> 4 [label="whiteSpace"] + 3 -> 6 [label="anyAttribute"] + 3 -> 4 [label="length"] + 3 -> 7 [label="assert"] + 3 -> 4 [label="maxExclusive"] + 3 -> 4 [label="enumeration"] + 3 -> 4 [label="assertion"] + 3 -> 4 [label="maxInclusive"] + 3 -> 5 [label="attribute"] + 3 -> 4 [label="maxLength"] + 3 -> 4 [label="pattern"] + 3 -> 4 [label="totalDigits"] + 3 -> 5 [label="attributeGroup"] + 3 -> 4 [label="minExclusive"] + 3 -> 4 [label="minInclusive"] + 4 -> 4 [label="fractionDigits"] + 4 -> 4 [label="minLength"] + 4 -> 4 [label="whiteSpace"] + 4 -> 6 [label="anyAttribute"] + 4 -> 4 [label="length"] + 4 -> 7 [label="assert"] + 4 -> 4 [label="maxExclusive"] + 4 -> 4 [label="enumeration"] + 4 -> 4 [label="assertion"] + 4 -> 4 [label="maxInclusive"] + 4 -> 5 [label="attribute"] + 4 -> 4 [label="maxLength"] + 4 -> 4 [label="pattern"] + 4 -> 4 [label="totalDigits"] + 4 -> 5 [label="attributeGroup"] + 4 -> 4 [label="minExclusive"] + 4 -> 4 [label="minInclusive"] + 5 -> 6 [label="anyAttribute"] + 5 -> 7 [label="assert"] + 5 -> 5 [label="attribute"] + 5 -> 5 [label="attributeGroup"] + 6 -> 7 [label="assert"] + 7 -> 7 [label="assert"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] + 3 [shape=doublecircle, style=filled, color=green] + 4 [shape=doublecircle, style=filled, color=green] + 5 [shape=doublecircle, style=filled, color=green] + 6 [shape=doublecircle, style=filled, color=green] + 7 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/SimpleContent_diagram.dot b/src/xmlpatterns/schema/doc/SimpleContent_diagram.dot new file mode 100644 index 0000000..c996329 --- /dev/null +++ b/src/xmlpatterns/schema/doc/SimpleContent_diagram.dot @@ -0,0 +1,11 @@ +digraph SimpleContent { + mindist = 2.0 + 1 -> 3 [label="restriction"] + 1 -> 2 [label="annotation"] + 1 -> 3 [label="extension"] + 2 -> 3 [label="restriction"] + 2 -> 3 [label="extension"] + 1 [shape=circle, style=filled, color=blue] + 2 [shape=circle, style=filled, color=red] + 3 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/SimpleRestriction_diagram.dot b/src/xmlpatterns/schema/doc/SimpleRestriction_diagram.dot new file mode 100644 index 0000000..09cb041 --- /dev/null +++ b/src/xmlpatterns/schema/doc/SimpleRestriction_diagram.dot @@ -0,0 +1,62 @@ +digraph SimpleRestriction { + mindist = 2.0 + 1 -> 4 [label="fractionDigits"] + 1 -> 4 [label="minLength"] + 1 -> 4 [label="whiteSpace"] + 1 -> 2 [label="annotation"] + 1 -> 3 [label="simpleType"] + 1 -> 4 [label="length"] + 1 -> 4 [label="maxExclusive"] + 1 -> 4 [label="enumeration"] + 1 -> 4 [label="assertion"] + 1 -> 4 [label="maxInclusive"] + 1 -> 4 [label="maxLength"] + 1 -> 4 [label="pattern"] + 1 -> 4 [label="totalDigits"] + 1 -> 4 [label="minExclusive"] + 1 -> 4 [label="minInclusive"] + 2 -> 4 [label="fractionDigits"] + 2 -> 4 [label="minLength"] + 2 -> 4 [label="whiteSpace"] + 2 -> 3 [label="simpleType"] + 2 -> 4 [label="length"] + 2 -> 4 [label="maxExclusive"] + 2 -> 4 [label="enumeration"] + 2 -> 4 [label="assertion"] + 2 -> 4 [label="maxInclusive"] + 2 -> 4 [label="maxLength"] + 2 -> 4 [label="pattern"] + 2 -> 4 [label="totalDigits"] + 2 -> 4 [label="minExclusive"] + 2 -> 4 [label="minInclusive"] + 3 -> 4 [label="fractionDigits"] + 3 -> 4 [label="minLength"] + 3 -> 4 [label="whiteSpace"] + 3 -> 4 [label="length"] + 3 -> 4 [label="maxExclusive"] + 3 -> 4 [label="enumeration"] + 3 -> 4 [label="assertion"] + 3 -> 4 [label="maxInclusive"] + 3 -> 4 [label="maxLength"] + 3 -> 4 [label="pattern"] + 3 -> 4 [label="totalDigits"] + 3 -> 4 [label="minExclusive"] + 3 -> 4 [label="minInclusive"] + 4 -> 4 [label="fractionDigits"] + 4 -> 4 [label="minLength"] + 4 -> 4 [label="whiteSpace"] + 4 -> 4 [label="length"] + 4 -> 4 [label="maxExclusive"] + 4 -> 4 [label="enumeration"] + 4 -> 4 [label="assertion"] + 4 -> 4 [label="maxInclusive"] + 4 -> 4 [label="maxLength"] + 4 -> 4 [label="pattern"] + 4 -> 4 [label="totalDigits"] + 4 -> 4 [label="minExclusive"] + 4 -> 4 [label="minInclusive"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] + 3 [shape=doublecircle, style=filled, color=green] + 4 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/TotalDigitsFacet_diagram.dot b/src/xmlpatterns/schema/doc/TotalDigitsFacet_diagram.dot new file mode 100644 index 0000000..0ef4cd6 --- /dev/null +++ b/src/xmlpatterns/schema/doc/TotalDigitsFacet_diagram.dot @@ -0,0 +1,6 @@ +digraph TotalDigitsFacet { + mindist = 2.0 + 1 -> 2 [label="annotation"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/Union_diagram.dot b/src/xmlpatterns/schema/doc/Union_diagram.dot new file mode 100644 index 0000000..d6c1865 --- /dev/null +++ b/src/xmlpatterns/schema/doc/Union_diagram.dot @@ -0,0 +1,10 @@ +digraph Union { + mindist = 2.0 + 1 -> 2 [label="annotation"] + 1 -> 3 [label="simpleType"] + 2 -> 3 [label="simpleType"] + 3 -> 3 [label="simpleType"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] + 3 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/Unique_diagram.dot b/src/xmlpatterns/schema/doc/Unique_diagram.dot new file mode 100644 index 0000000..5b1d098 --- /dev/null +++ b/src/xmlpatterns/schema/doc/Unique_diagram.dot @@ -0,0 +1,12 @@ +digraph Unique { + mindist = 2.0 + 1 -> 2 [label="annotation"] + 1 -> 3 [label="selector"] + 2 -> 3 [label="selector"] + 3 -> 4 [label="field"] + 4 -> 4 [label="field"] + 1 [shape=circle, style=filled, color=blue] + 2 [shape=circle, style=filled, color=red] + 3 [shape=circle, style=filled, color=red] + 4 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/WhiteSpaceFacet_diagram.dot b/src/xmlpatterns/schema/doc/WhiteSpaceFacet_diagram.dot new file mode 100644 index 0000000..596403c --- /dev/null +++ b/src/xmlpatterns/schema/doc/WhiteSpaceFacet_diagram.dot @@ -0,0 +1,6 @@ +digraph WhiteSpaceFacet { + mindist = 2.0 + 1 -> 2 [label="annotation"] + 1 [shape=doublecircle, style=filled, color=blue] + 2 [shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/doc/legend.dot b/src/xmlpatterns/schema/doc/legend.dot new file mode 100644 index 0000000..4f5792e --- /dev/null +++ b/src/xmlpatterns/schema/doc/legend.dot @@ -0,0 +1,7 @@ +digraph { + size="5,4" + 1 [label=" start state ", shape=circle, style=filled, color=blue] + 2 [label="start/end state", shape=doublecircle, style=filled, color=blue] + 3 [label=" internal state", shape=circle, style=filled, color=red] + 4 [label=" end state ", shape=doublecircle, style=filled, color=green] +} diff --git a/src/xmlpatterns/schema/qnamespacesupport.cpp b/src/xmlpatterns/schema/qnamespacesupport.cpp new file mode 100644 index 0000000..00698d6 --- /dev/null +++ b/src/xmlpatterns/schema/qnamespacesupport.cpp @@ -0,0 +1,132 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#include "qnamespacesupport_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +NamespaceSupport::NamespaceSupport() +{ +} + +NamespaceSupport::NamespaceSupport(const NamePool::Ptr &namePool) + : m_namePool(namePool) +{ + // the XML namespace + const QXmlName binding = namePool->allocateBinding(QLatin1String("xml"), + QLatin1String("http://www.w3.org/XML/1998/namespace")); + m_ns.insert(binding.prefix(), binding.namespaceURI()); +} + +void NamespaceSupport::setPrefix(const QXmlName::PrefixCode prefixCode, const QXmlName::NamespaceCode namespaceCode) +{ + m_ns.insert(prefixCode, namespaceCode); +} + +void NamespaceSupport::setPrefixes(const QXmlStreamNamespaceDeclarations &declarations) +{ + for (int i = 0; i < declarations.count(); i++) { + const QXmlStreamNamespaceDeclaration declaration = declarations.at(i); + + const QXmlName::PrefixCode prefixCode = m_namePool->allocatePrefix(declaration.prefix().toString()); + const QXmlName::NamespaceCode namespaceCode = m_namePool->allocateNamespace(declaration.namespaceUri().toString()); + m_ns.insert(prefixCode, namespaceCode); + } +} + +void NamespaceSupport::setTargetNamespace(const QXmlName::NamespaceCode namespaceCode) +{ + m_ns.insert(0, namespaceCode); +} + +QXmlName::PrefixCode NamespaceSupport::prefix(const QXmlName::NamespaceCode namespaceCode) const +{ + NamespaceHash::const_iterator itc, it = m_ns.constBegin(); + while ((itc=it) != m_ns.constEnd()) { + ++it; + if (*itc == namespaceCode) + return itc.key(); + } + return 0; +} + +QXmlName::NamespaceCode NamespaceSupport::uri(const QXmlName::PrefixCode prefixCode) const +{ + return m_ns.value(prefixCode); +} + +bool NamespaceSupport::processName(const QString& qname, NameType type, QXmlName &name) const +{ + int len = qname.size(); + const QChar *data = qname.constData(); + for (int pos = 0; pos < len; ++pos) { + if (data[pos] == QLatin1Char(':')) { + const QXmlName::PrefixCode prefixCode = m_namePool->allocatePrefix(qname.left(pos)); + if (!m_ns.contains(prefixCode)) + return false; + const QXmlName::NamespaceCode namespaceCode = uri(prefixCode); + const QXmlName::LocalNameCode localNameCode = m_namePool->allocateLocalName(qname.mid(pos + 1)); + name = QXmlName(namespaceCode, localNameCode, prefixCode); + return true; + } + } + + // there was no ':' + QXmlName::NamespaceCode namespaceCode = 0; + // attributes don't take default namespace + if (type == ElementName && !m_ns.isEmpty()) { + namespaceCode = m_ns.value(0); // get default namespace + } + + const QXmlName::LocalNameCode localNameCode = m_namePool->allocateLocalName(qname); + name = QXmlName(namespaceCode, localNameCode, 0); + + return true; +} + +void NamespaceSupport::pushContext() +{ + m_nsStack.push(m_ns); +} + +void NamespaceSupport::popContext() +{ + m_ns.clear(); + if(!m_nsStack.isEmpty()) + m_ns = m_nsStack.pop(); +} + +QList NamespaceSupport::namespaceBindings() const +{ + QList bindings; + + QHashIterator it(m_ns); + while (it.hasNext()) { + it.next(); + bindings.append(QXmlName(it.value(), StandardLocalNames::empty, it.key())); + } + + return bindings; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qnamespacesupport_p.h b/src/xmlpatterns/schema/qnamespacesupport_p.h new file mode 100644 index 0000000..d338eae --- /dev/null +++ b/src/xmlpatterns/schema/qnamespacesupport_p.h @@ -0,0 +1,143 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_NamespaceSupport_H +#define Patternist_NamespaceSupport_H + +#include "qnamepool_p.h" + +#include +#include +#include +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short A helper class for handling nested namespace declarations. + * + * This class is mostly an adaption of QXmlNamespaceSupport to the NamePool + * mechanism used in XmlPatterns. + * + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class NamespaceSupport + { + public: + /** + * Describes whether the name to process is an attribute or element. + */ + enum NameType + { + AttributeName, ///< An attribute name to process. + ElementName ///< An element name to process. + }; + + /** + * Creates an empty namespace support object. + */ + NamespaceSupport(); + + /** + * Creates a new namespace support object. + * + * @param namePool The name pool where all processed names are stored in. + */ + NamespaceSupport(const NamePool::Ptr &namePool); + + /** + * Adds a new prefix-to-namespace binding. + * + * @param prefixCode The name pool code for the prefix. + * @param namespaceCode The name pool code for the namespace. + */ + void setPrefix(const QXmlName::PrefixCode prefixCode, const QXmlName::NamespaceCode namespaceCode); + + /** + * Adds the prefix-to-namespace bindings from @p declarations to + * the namespace support. + */ + void setPrefixes(const QXmlStreamNamespaceDeclarations &declarations); + + /** + * Sets the name pool code of the target namespace of the schema the + * namespace support works on. + */ + void setTargetNamespace(const QXmlName::NamespaceCode code); + + /** + * Returns the prefix code for the given namespace @p code. + */ + QXmlName::PrefixCode prefix(const QXmlName::NamespaceCode code) const; + + /** + * Returns the namespace code for the given prefix @p code. + */ + QXmlName::NamespaceCode uri(const QXmlName::PrefixCode code) const; + + /** + * Converts the given @p qualifiedName to a resolved QXmlName @p name according + * to the current namespace mapping. + * + * @param qualifiedName The full qualified name. + * @param type The type of name processing. + * @param name The resolved QXmlName. + * + * @returns @c true if the name could be processed correctly or @c false if the + * namespace prefix is unknown. + */ + bool processName(const QString &qualifiedName, NameType type, QXmlName &name) const; + + /** + * Pushes the current namespace mapping onto the stack. + */ + void pushContext(); + + /** + * Pops the current namespace mapping from the stack. + */ + void popContext(); + + /** + * Returns the list of namespace bindings. + */ + QList namespaceBindings() const; + + private: + typedef QHash NamespaceHash; + + NamePool::Ptr m_namePool; + QStack m_nsStack; + NamespaceHash m_ns; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsdalternative.cpp b/src/xmlpatterns/schema/qxsdalternative.cpp new file mode 100644 index 0000000..f3f589a --- /dev/null +++ b/src/xmlpatterns/schema/qxsdalternative.cpp @@ -0,0 +1,38 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qxsdalternative_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +void XsdAlternative::setTest(const XsdXPathExpression::Ptr &test) +{ + m_test = test; +} + +XsdXPathExpression::Ptr XsdAlternative::test() const +{ + return m_test; +} + +void XsdAlternative::setType(const SchemaType::Ptr &type) +{ + m_type = type; +} + +SchemaType::Ptr XsdAlternative::type() const +{ + return m_type; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdalternative_p.h b/src/xmlpatterns/schema/qxsdalternative_p.h new file mode 100644 index 0000000..451441e --- /dev/null +++ b/src/xmlpatterns/schema/qxsdalternative_p.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdAlternative_H +#define Patternist_XsdAlternative_H + +#include "qnamedschemacomponent_p.h" +#include "qschematype_p.h" +#include "qxsdannotated_p.h" +#include "qxsdxpathexpression_p.h" + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Represents a XSD alternative object. + * + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdAlternative : public NamedSchemaComponent, public XsdAnnotated + { + public: + typedef QExplicitlySharedDataPointer Ptr; + typedef QList List; + + /** + * Sets the xpath @p test of the alternative. + * + * @see Test Definition + */ + void setTest(const XsdXPathExpression::Ptr &test); + + /** + * Returns the xpath test of the alternative. + */ + XsdXPathExpression::Ptr test() const; + + /** + * Sets the @p type of the alternative. + * + * @see Type Definition + */ + void setType(const SchemaType::Ptr &type); + + /** + * Returns the type of the alternative. + */ + SchemaType::Ptr type() const; + + private: + XsdXPathExpression::Ptr m_test; + SchemaType::Ptr m_type; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsdannotated.cpp b/src/xmlpatterns/schema/qxsdannotated.cpp new file mode 100644 index 0000000..a29b5c4 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdannotated.cpp @@ -0,0 +1,33 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qxsdannotated_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +void XsdAnnotated::addAnnotation(const XsdAnnotation::Ptr &annotation) +{ + m_annotations.append(annotation); +} + +void XsdAnnotated::addAnnotations(const XsdAnnotation::List &annotations) +{ + m_annotations << annotations; +} + +XsdAnnotation::List XsdAnnotated::annotations() const +{ + return m_annotations; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdannotated_p.h b/src/xmlpatterns/schema/qxsdannotated_p.h new file mode 100644 index 0000000..251b252 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdannotated_p.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdAnnotated_H +#define Patternist_XsdAnnotated_H + +#include "qxsdannotation_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Base class for all XSD components with annotation content. + * + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdAnnotated + { + public: + /** + * Adds a new @p annotation to the component. + */ + void addAnnotation(const XsdAnnotation::Ptr &annotation); + + /** + * Adds a list of new @p annotations to the component. + */ + void addAnnotations(const XsdAnnotation::List &annotations); + + /** + * Returns the list of all annotations of the component. + */ + XsdAnnotation::List annotations() const; + + private: + XsdAnnotation::List m_annotations; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsdannotation.cpp b/src/xmlpatterns/schema/qxsdannotation.cpp new file mode 100644 index 0000000..0a9dc04 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdannotation.cpp @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qxsdannotation_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +void XsdAnnotation::setId(const DerivedString::Ptr &id) +{ + m_id = id; +} + +DerivedString::Ptr XsdAnnotation::id() const +{ + return m_id; +} + +void XsdAnnotation::addApplicationInformation(const XsdApplicationInformation::Ptr &information) +{ + m_applicationInformation.append(information); +} + +XsdApplicationInformation::List XsdAnnotation::applicationInformation() const +{ + return m_applicationInformation; +} + +void XsdAnnotation::addDocumentation(const XsdDocumentation::Ptr &documentation) +{ + m_documentations.append(documentation); +} + +XsdDocumentation::List XsdAnnotation::documentation() const +{ + return m_documentations; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdannotation_p.h b/src/xmlpatterns/schema/qxsdannotation_p.h new file mode 100644 index 0000000..8c23bae --- /dev/null +++ b/src/xmlpatterns/schema/qxsdannotation_p.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdAnnotation_H +#define Patternist_XsdAnnotation_H + +#include "qderivedstring_p.h" +#include "qxsdapplicationinformation_p.h" +#include "qxsddocumentation_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Represents a XSD annotation object. + * + * This class represents the annotation object of a XML schema as described + * here. + * + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdAnnotation : public NamedSchemaComponent + { + public: + typedef QExplicitlySharedDataPointer Ptr; + typedef QList List; + + /** + * Sets the @p id of the annotation. + */ + void setId(const DerivedString::Ptr &id); + + /** + * Returns the @p id of the annotation. + */ + DerivedString::Ptr id() const; + + /** + * Adds an application @p information to the annotation. + * + * The application information is meant to be interpreted by + * a software system, e.g. other parts of the XML processor pipeline. + */ + void addApplicationInformation(const XsdApplicationInformation::Ptr &information); + + /** + * Returns the list of all application information of the annotation. + */ + XsdApplicationInformation::List applicationInformation() const; + + /** + * Adds a @p documentation to the annotation. + * + * The documentation is meant to be read by human being, e.g. additional + * constraints or information about schema components. + */ + void addDocumentation(const XsdDocumentation::Ptr &documentation); + + /** + * Returns the list of all documentations of the annotation. + */ + XsdDocumentation::List documentation() const; + + private: + DerivedString::Ptr m_id; + XsdApplicationInformation::List m_applicationInformation; + XsdDocumentation::List m_documentations; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsdapplicationinformation.cpp b/src/xmlpatterns/schema/qxsdapplicationinformation.cpp new file mode 100644 index 0000000..5669220 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdapplicationinformation.cpp @@ -0,0 +1,38 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qxsdapplicationinformation_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +void XsdApplicationInformation::setSource(const AnyURI::Ptr &source) +{ + m_source = source; +} + +AnyURI::Ptr XsdApplicationInformation::source() const +{ + return m_source; +} + +void XsdApplicationInformation::setContent(const QString &content) +{ + m_content = content; +} + +QString XsdApplicationInformation::content() const +{ + return m_content; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdapplicationinformation_p.h b/src/xmlpatterns/schema/qxsdapplicationinformation_p.h new file mode 100644 index 0000000..30839d3 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdapplicationinformation_p.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdApplicationInformation_H +#define Patternist_XsdApplicationInformation_H + +#include "qanytype_p.h" +#include "qanyuri_p.h" +#include "qnamedschemacomponent_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Represents a XSD appinfo object. + * + * This class represents the appinfo component of an annotation object + * of a XML schema as described here. + * + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdApplicationInformation : public NamedSchemaComponent + { + public: + typedef QExplicitlySharedDataPointer Ptr; + typedef QList List; + + /** + * Sets the @p source of the application information. + * + * The source points to an URL that contains more + * information. + */ + void setSource(const AnyURI::Ptr &source); + + /** + * Returns the source of the application information. + */ + AnyURI::Ptr source() const; + + /** + * Sets the @p content of the application information. + * + * The content can be of abritrary type. + */ + void setContent(const QString &content); + + /** + * Returns the content of the application information. + */ + QString content() const; + + private: + AnyURI::Ptr m_source; + QString m_content; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsdassertion.cpp b/src/xmlpatterns/schema/qxsdassertion.cpp new file mode 100644 index 0000000..f6cbf81 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdassertion.cpp @@ -0,0 +1,28 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qxsdassertion_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +void XsdAssertion::setTest(const XsdXPathExpression::Ptr &test) +{ + m_test = test; +} + +XsdXPathExpression::Ptr XsdAssertion::test() const +{ + return m_test; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdassertion_p.h b/src/xmlpatterns/schema/qxsdassertion_p.h new file mode 100644 index 0000000..0ae5ff6 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdassertion_p.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdAssertion_H +#define Patternist_XsdAssertion_H + +#include "qnamedschemacomponent_p.h" +#include "qxsdannotated_p.h" +#include "qxsdxpathexpression_p.h" + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Represents a XSD assertion object. + * + * @ingroup Patternist_schema + * @author Tobias Koenig + * @see Assertion Definition + */ + class XsdAssertion : public NamedSchemaComponent, public XsdAnnotated + { + public: + typedef QExplicitlySharedDataPointer Ptr; + typedef QList List; + + /** + * Sets the @p test of the assertion. + * + * @see Test Definition + */ + void setTest(const XsdXPathExpression::Ptr &test); + + /** + * Returns the test of the assertion. + */ + XsdXPathExpression::Ptr test() const; + + private: + XsdXPathExpression::Ptr m_test; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsdattribute.cpp b/src/xmlpatterns/schema/qxsdattribute.cpp new file mode 100644 index 0000000..6cf60ec --- /dev/null +++ b/src/xmlpatterns/schema/qxsdattribute.cpp @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qxsdattribute_p.h" +#include "qxsdcomplextype_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + + +void XsdAttribute::Scope::setVariety(Variety variety) +{ + m_variety = variety; +} + +XsdAttribute::Scope::Variety XsdAttribute::Scope::variety() const +{ + return m_variety; +} + +void XsdAttribute::Scope::setParent(const NamedSchemaComponent::Ptr &parent) +{ + m_parent = parent; +} + +NamedSchemaComponent::Ptr XsdAttribute::Scope::parent() const +{ + return m_parent; +} + +void XsdAttribute::ValueConstraint::setVariety(Variety variety) +{ + m_variety = variety; +} + +XsdAttribute::ValueConstraint::Variety XsdAttribute::ValueConstraint::variety() const +{ + return m_variety; +} + +void XsdAttribute::ValueConstraint::setValue(const QString &value) +{ + m_value = value; +} + +QString XsdAttribute::ValueConstraint::value() const +{ + return m_value; +} + +void XsdAttribute::ValueConstraint::setLexicalForm(const QString &form) +{ + m_lexicalForm = form; +} + +QString XsdAttribute::ValueConstraint::lexicalForm() const +{ + return m_lexicalForm; +} + +void XsdAttribute::setType(const AnySimpleType::Ptr &type) +{ + m_type = type; +} + +AnySimpleType::Ptr XsdAttribute::type() const +{ + return m_type; +} + +void XsdAttribute::setScope(const Scope::Ptr &scope) +{ + m_scope = scope; +} + +XsdAttribute::Scope::Ptr XsdAttribute::scope() const +{ + return m_scope; +} + +void XsdAttribute::setValueConstraint(const ValueConstraint::Ptr &constraint) +{ + m_valueConstraint = constraint; +} + +XsdAttribute::ValueConstraint::Ptr XsdAttribute::valueConstraint() const +{ + return m_valueConstraint; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdattribute_p.h b/src/xmlpatterns/schema/qxsdattribute_p.h new file mode 100644 index 0000000..46d7355 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdattribute_p.h @@ -0,0 +1,216 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdAttribute_H +#define Patternist_XsdAttribute_H + +#include "qanysimpletype_p.h" +#include "qnamedschemacomponent_p.h" +#include "qxsdannotated_p.h" + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Represents a XSD attribute object. + * + * This class represents the attribute object of a XML schema as described + * here. + * + * It contains information from either a top-level attribute declaration (as child of + * a schema object) or of a local attribute declaration (as child of complexType + * or attributeGroup object without a 'ref' attribute). + * + * All other occurrences of the attribute object are represented by the XsdAttributeUse class. + * + * @see XML Schema API reference + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdAttribute : public NamedSchemaComponent, public XsdAnnotated + { + public: + typedef QExplicitlySharedDataPointer Ptr; + typedef QList List; + + /** + * @short Describes the scope of an attribute. + * + * @see Scope Definition + */ + class Scope : public QSharedData + { + public: + typedef QExplicitlySharedDataPointer Ptr; + + /** + * Describes the scope of an attribute. + */ + enum Variety + { + Global, ///< The attribute is defined globally as child of the schema object. + Local ///< The attribute is defined locally as child of a complex type or attribute group definition. + }; + + /** + * Sets the @p variety of the attribute scope. + * + * @see Variety Definition + */ + void setVariety(Variety variety); + + /** + * Returns the variety of the attribute scope. + */ + Variety variety() const; + + /** + * Sets the @p parent complex type or attribute group definition of the attribute scope. + * + * @see Parent Definition + */ + void setParent(const NamedSchemaComponent::Ptr &parent); + + /** + * Returns the parent complex type or attribute group definition of the attribute scope. + */ + NamedSchemaComponent::Ptr parent() const; + + private: + Variety m_variety; + NamedSchemaComponent::Ptr m_parent; + }; + + + /** + * @short Describes the value constraint of an attribute. + * + * @see Value Constraint Definition + */ + class ValueConstraint : public QSharedData + { + public: + typedef QExplicitlySharedDataPointer Ptr; + + /** + * Describes the value constraint of an attribute. + */ + enum Variety + { + Default, ///< The attribute has a default value set. + Fixed ///< The attribute has a fixed value set. + }; + + /** + * Sets the @p variety of the attribute value constraint. + * + * @see Variety Definition + */ + void setVariety(Variety variety); + + /** + * Returns the variety of the attribute value constraint. + */ + Variety variety() const; + + /** + * Sets the @p value of the constraint. + * + * @see Value Definition + */ + void setValue(const QString &value); + + /** + * Returns the value of the constraint. + */ + QString value() const; + + /** + * Sets the lexical @p form of the constraint. + * + * @see Lexical Form Definition + */ + void setLexicalForm(const QString &form); + + /** + * Returns the lexical form of the constraint. + */ + QString lexicalForm() const; + + private: + Variety m_variety; + QString m_value; + QString m_lexicalForm; + }; + + /** + * Sets the simple @p type definition of the attribute. + * + * @see Simple Type Definition + */ + void setType(const AnySimpleType::Ptr &type); + + /** + * Returns the simple type definition of the attribute. + */ + AnySimpleType::Ptr type() const; + + /** + * Sets the @p scope of the attribute. + * + * @see Scope Definition + */ + void setScope(const Scope::Ptr &scope); + + /** + * Returns the scope of the attribute. + */ + Scope::Ptr scope() const; + + /** + * Sets the value @p constraint of the attribute. + * + * @see Value Constraint Definition + */ + void setValueConstraint(const ValueConstraint::Ptr &constraint); + + /** + * Returns the value constraint of the attribute. + */ + ValueConstraint::Ptr valueConstraint() const; + + private: + AnySimpleType::Ptr m_type; + Scope::Ptr m_scope; + ValueConstraint::Ptr m_valueConstraint; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsdattributegroup.cpp b/src/xmlpatterns/schema/qxsdattributegroup.cpp new file mode 100644 index 0000000..8f2a47e --- /dev/null +++ b/src/xmlpatterns/schema/qxsdattributegroup.cpp @@ -0,0 +1,43 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qxsdattributegroup_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +void XsdAttributeGroup::setAttributeUses(const XsdAttributeUse::List &attributeUses) +{ + m_attributeUses = attributeUses; +} + +void XsdAttributeGroup::addAttributeUse(const XsdAttributeUse::Ptr &attributeUse) +{ + m_attributeUses.append(attributeUse); +} + +XsdAttributeUse::List XsdAttributeGroup::attributeUses() const +{ + return m_attributeUses; +} + +void XsdAttributeGroup::setWildcard(const XsdWildcard::Ptr &wildcard) +{ + m_wildcard = wildcard; +} + +XsdWildcard::Ptr XsdAttributeGroup::wildcard() const +{ + return m_wildcard; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdattributegroup_p.h b/src/xmlpatterns/schema/qxsdattributegroup_p.h new file mode 100644 index 0000000..7a3bd79 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdattributegroup_p.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdAttributeGroup_H +#define Patternist_XsdAttributeGroup_H + +#include "qxsdannotated_p.h" +#include "qxsdattributeuse_p.h" +#include "qxsdwildcard_p.h" + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Represents the XSD attributeGroup object. + * + * This class represents the attributeGroup object of a XML schema as described + * here. + * + * @see XML Schema API reference + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdAttributeGroup : public NamedSchemaComponent, public XsdAnnotated + { + public: + typedef QExplicitlySharedDataPointer Ptr; + typedef QList List; + + /** + * Sets the list of attribute @p uses that are defined in the attribute group. + * + * @see Attribute Uses + */ + void setAttributeUses(const XsdAttributeUse::List &uses); + + /** + * Adds a new attribute @p use to the attribute group. + */ + void addAttributeUse(const XsdAttributeUse::Ptr &use); + + /** + * Returns the list of all attribute uses of the attribute group. + */ + XsdAttributeUse::List attributeUses() const; + + /** + * Sets the attribute @p wildcard of the attribute group. + * + * @see Attribute Wildcard + */ + void setWildcard(const XsdWildcard::Ptr &wildcard); + + /** + * Returns the attribute wildcard of the attribute group. + */ + XsdWildcard::Ptr wildcard() const; + + private: + XsdAttributeUse::List m_attributeUses; + XsdWildcard::Ptr m_wildcard; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsdattributereference.cpp b/src/xmlpatterns/schema/qxsdattributereference.cpp new file mode 100644 index 0000000..3c36a4e --- /dev/null +++ b/src/xmlpatterns/schema/qxsdattributereference.cpp @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qxsdattributereference_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +bool XsdAttributeReference::isAttributeUse() const +{ + return false; +} + +bool XsdAttributeReference::isReference() const +{ + return true; +} + +void XsdAttributeReference::setType(Type type) +{ + m_type = type; +} + +XsdAttributeReference::Type XsdAttributeReference::type() const +{ + return m_type; +} + +void XsdAttributeReference::setReferenceName(const QXmlName &referenceName) +{ + m_referenceName = referenceName; +} + +QXmlName XsdAttributeReference::referenceName() const +{ + return m_referenceName; +} + +void XsdAttributeReference::setSourceLocation(const QSourceLocation &location) +{ + m_sourceLocation = location; +} + +QSourceLocation XsdAttributeReference::sourceLocation() const +{ + return m_sourceLocation; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdattributereference_p.h b/src/xmlpatterns/schema/qxsdattributereference_p.h new file mode 100644 index 0000000..be48b3a --- /dev/null +++ b/src/xmlpatterns/schema/qxsdattributereference_p.h @@ -0,0 +1,117 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdAttributeReference_H +#define Patternist_XsdAttributeReference_H + +#include "qxsdattributeuse_p.h" + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short A helper class for attribute reference resolving. + * + * For easy resolving of attribute references, we have this class + * that can be used as a place holder for the real attribute use + * object it is referring to. + * So whenever the parser detects an attribute reference, it creates + * a XsdAttributeReference and returns it instead of the XsdAttributeUse. + * During a later phase, the resolver will look for all XsdAttributeReferences + * in the schema and will replace them with their referring XsdAttributeUse + * objects. + * + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdAttributeReference : public XsdAttributeUse + { + public: + typedef QExplicitlySharedDataPointer Ptr; + + /** + * Describes the type of the attribute reference. + */ + enum Type + { + AttributeUse, ///< The reference points to an attribute use. + AttributeGroup ///< The reference points to an attribute group. + }; + + /** + * Always returns false, used to avoid dynamic casts. + */ + virtual bool isAttributeUse() const; + + /** + * Always returns true, used to avoid dynamic casts. + */ + virtual bool isReference() const; + + /** + * Sets the @p type of the attribute reference. + */ + void setType(Type type); + + /** + * Returns the type of the attribute reference. + */ + Type type() const; + + /** + * Sets the @p name of the attribute or attribute group the + * attribute reference refers to. + */ + void setReferenceName(const QXmlName &name); + + /** + * Returns the name of the attribute or attribute group the + * attribute reference refers to. + */ + QXmlName referenceName() const; + + /** + * Sets the source @p location where the reference is located. + */ + void setSourceLocation(const QSourceLocation &location); + + /** + * Returns the source location where the reference is located. + */ + QSourceLocation sourceLocation() const; + + private: + Type m_type; + QXmlName m_referenceName; + QSourceLocation m_sourceLocation; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsdattributeterm.cpp b/src/xmlpatterns/schema/qxsdattributeterm.cpp new file mode 100644 index 0000000..a9c3898 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdattributeterm.cpp @@ -0,0 +1,28 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qxsdattributeterm_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +bool XsdAttributeTerm::isAttributeUse() const +{ + return false; +} + +bool XsdAttributeTerm::isReference() const +{ + return false; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdattributeterm_p.h b/src/xmlpatterns/schema/qxsdattributeterm_p.h new file mode 100644 index 0000000..507df32 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdattributeterm_p.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdAttributeTerm_H +#define Patternist_XsdAttributeTerm_H + +#include "qnamedschemacomponent_p.h" +#include "qxsdannotated_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short A base class for all attribute types. + * + * For easy resolving of attribute references, we use this as + * common base class for XsdAttribute and XsdAttributeReference. + * + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdAttributeTerm : public NamedSchemaComponent, public XsdAnnotated + { + public: + typedef QExplicitlySharedDataPointer Ptr; + + /** + * Returns @c true if the term is an attribute use, @c false otherwise. + */ + virtual bool isAttributeUse() const; + + /** + * Returns @c true if the term is an attribute use reference, @c false otherwise. + * + * @note The reference term is only used internally as helper during type resolving. + */ + virtual bool isReference() const; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsdattributeuse.cpp b/src/xmlpatterns/schema/qxsdattributeuse.cpp new file mode 100644 index 0000000..96d81bc --- /dev/null +++ b/src/xmlpatterns/schema/qxsdattributeuse.cpp @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qxsdattributeuse_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +void XsdAttributeUse::ValueConstraint::setVariety(Variety variety) +{ + m_variety = variety; +} + +XsdAttributeUse::ValueConstraint::Variety XsdAttributeUse::ValueConstraint::variety() const +{ + return m_variety; +} + +void XsdAttributeUse::ValueConstraint::setValue(const QString &value) +{ + m_value = value; +} + +QString XsdAttributeUse::ValueConstraint::value() const +{ + return m_value; +} + +void XsdAttributeUse::ValueConstraint::setLexicalForm(const QString &form) +{ + m_lexicalForm = form; +} + +QString XsdAttributeUse::ValueConstraint::lexicalForm() const +{ + return m_lexicalForm; +} + +XsdAttributeUse::ValueConstraint::Ptr XsdAttributeUse::ValueConstraint::fromAttributeValueConstraint(const XsdAttribute::ValueConstraint::Ptr &constraint) +{ + XsdAttributeUse::ValueConstraint::Ptr newConstraint(new XsdAttributeUse::ValueConstraint()); + switch (constraint->variety()) { + case XsdAttribute::ValueConstraint::Fixed: newConstraint->setVariety(Fixed); break; + case XsdAttribute::ValueConstraint::Default: newConstraint->setVariety(Default); break; + } + newConstraint->setValue(constraint->value()); + newConstraint->setLexicalForm(constraint->lexicalForm()); + + return newConstraint; +} + +XsdAttributeUse::XsdAttributeUse() + : m_useType(OptionalUse) +{ +} + +bool XsdAttributeUse::isAttributeUse() const +{ + return true; +} + +void XsdAttributeUse::setUseType(UseType type) +{ + m_useType = type; +} + +XsdAttributeUse::UseType XsdAttributeUse::useType() const +{ + return m_useType; +} + +bool XsdAttributeUse::isRequired() const +{ + return (m_useType == RequiredUse); +} + +void XsdAttributeUse::setAttribute(const XsdAttribute::Ptr &attribute) +{ + m_attribute = attribute; +} + +XsdAttribute::Ptr XsdAttributeUse::attribute() const +{ + return m_attribute; +} + +void XsdAttributeUse::setValueConstraint(const ValueConstraint::Ptr &constraint) +{ + m_valueConstraint = constraint; +} + +XsdAttributeUse::ValueConstraint::Ptr XsdAttributeUse::valueConstraint() const +{ + return m_valueConstraint; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdattributeuse_p.h b/src/xmlpatterns/schema/qxsdattributeuse_p.h new file mode 100644 index 0000000..86021e1 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdattributeuse_p.h @@ -0,0 +1,194 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdAttributeUse_H +#define Patternist_XsdAttributeUse_H + +#include "qxsdattribute_p.h" +#include "qxsdattributeterm_p.h" + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Represents a XSD attribute use object. + * + * This class represents the attribute use object of a XML schema as described + * here. + * + * It contains information from a local attribute declaration (as child of complexType + * or attributeGroup object). + * + * All other occurrences of the attribute object are represented by the XsdAttribute class. + * + * @see XML Schema API reference + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdAttributeUse : public XsdAttributeTerm + { + public: + typedef QExplicitlySharedDataPointer Ptr; + typedef QList List; + + /** + * Describes the value constraint of an attribute use. + * + * @see Value Constraint Definition + */ + class ValueConstraint : public QSharedData + { + public: + typedef QExplicitlySharedDataPointer Ptr; + + /** + * Describes the value constraint of an attribute use. + */ + enum Variety + { + Default, ///< The attribute use has a default value set. + Fixed ///< The attribute use has a fixed value set. + }; + + /** + * Sets the @p variety of the attribute use value constraint. + */ + void setVariety(Variety variety); + + /** + * Returns the variety of the attribute use value constraint. + */ + Variety variety() const; + + /** + * Sets the @p value of the constraint. + */ + void setValue(const QString &value); + + /** + * Returns the value of the constraint. + */ + QString value() const; + + /** + * Sets the lexical @p form of the constraint. + */ + void setLexicalForm(const QString &form); + + /** + * Returns the lexical form of the constraint. + */ + QString lexicalForm() const; + + /** + * Creates a new value constraint from a XsdAttribute::ValueConstraint. + */ + static ValueConstraint::Ptr fromAttributeValueConstraint(const XsdAttribute::ValueConstraint::Ptr &constraint); + + private: + Variety m_variety; + QString m_value; + QString m_lexicalForm; + }; + + /** + * Describes the use type of the attribute use. + */ + enum UseType + { + OptionalUse, ///< The attribute can be there but doesn't need to. + RequiredUse, ///< The attribute must be there. + ProhibitedUse ///< The attribute is not allowed to be there. + }; + + /** + * Creates a new attribute use object. + */ + XsdAttributeUse(); + + /** + * Always returns true, used to avoid dynamic casts. + */ + virtual bool isAttributeUse() const; + + /** + * Sets the use @p type of the attribute use. + * + * @see UseType + */ + void setUseType(UseType type); + + /** + * Returns the use type of the attribute use. + */ + UseType useType() const; + + /** + * Returns whether the attribute use is required. + * + * @see Required Definition + */ + bool isRequired() const; + + /** + * Sets the @p attribute the attribute use is referring to. + * That is either a local definition as child of a complexType + * or attributeGroup object, or a reference defined by the + * 'ref' attribute. + * + * @see Attribute Declaration + */ + void setAttribute(const XsdAttribute::Ptr &attribute); + + /** + * Returns the attribute the attribute use is referring to. + */ + XsdAttribute::Ptr attribute() const; + + /** + * Sets the value @p constraint of the attribute use. + * + * @see http://www.w3.org/TR/xmlschema11-1/#vc_au + */ + void setValueConstraint(const ValueConstraint::Ptr &constraint); + + /** + * Returns the value constraint of the attribute use. + */ + ValueConstraint::Ptr valueConstraint() const; + + private: + UseType m_useType; + XsdAttribute::Ptr m_attribute; + ValueConstraint::Ptr m_valueConstraint; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsdcomplextype.cpp b/src/xmlpatterns/schema/qxsdcomplextype.cpp new file mode 100644 index 0000000..ddc9110 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdcomplextype.cpp @@ -0,0 +1,201 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qxsdcomplextype_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +void XsdComplexType::OpenContent::setMode(Mode mode) +{ + m_mode = mode; +} + +XsdComplexType::OpenContent::Mode XsdComplexType::OpenContent::mode() const +{ + return m_mode; +} + +void XsdComplexType::OpenContent::setWildcard(const XsdWildcard::Ptr &wildcard) +{ + m_wildcard = wildcard; +} + +XsdWildcard::Ptr XsdComplexType::OpenContent::wildcard() const +{ + return m_wildcard; +} + +void XsdComplexType::ContentType::setVariety(Variety variety) +{ + m_variety = variety; +} + +XsdComplexType::ContentType::Variety XsdComplexType::ContentType::variety() const +{ + return m_variety; +} + +void XsdComplexType::ContentType::setParticle(const XsdParticle::Ptr &particle) +{ + m_particle = particle; +} + +XsdParticle::Ptr XsdComplexType::ContentType::particle() const +{ + return m_particle; +} + +void XsdComplexType::ContentType::setOpenContent(const OpenContent::Ptr &content) +{ + m_openContent = content; +} + +XsdComplexType::OpenContent::Ptr XsdComplexType::ContentType::openContent() const +{ + return m_openContent; +} + +void XsdComplexType::ContentType::setSimpleType(const AnySimpleType::Ptr &type) +{ + m_simpleType = type; +} + +AnySimpleType::Ptr XsdComplexType::ContentType::simpleType() const +{ + return m_simpleType; +} + + +XsdComplexType::XsdComplexType() + : m_isAbstract(false) + , m_contentType(new ContentType()) +{ + m_contentType->setVariety(ContentType::Empty); +} + +void XsdComplexType::setIsAbstract(bool abstract) +{ + m_isAbstract = abstract; +} + +bool XsdComplexType::isAbstract() const +{ + return m_isAbstract; +} + +QString XsdComplexType::displayName(const NamePool::Ptr &np) const +{ + return np->displayName(name(np)); +} + +void XsdComplexType::setWxsSuperType(const SchemaType::Ptr &type) +{ + m_superType = type; +} + +SchemaType::Ptr XsdComplexType::wxsSuperType() const +{ + return m_superType; +} + +void XsdComplexType::setContext(const NamedSchemaComponent::Ptr &component) +{ + m_context = component; +} + +NamedSchemaComponent::Ptr XsdComplexType::context() const +{ + return m_context; +} + +void XsdComplexType::setContentType(const ContentType::Ptr &type) +{ + m_contentType = type; +} + +XsdComplexType::ContentType::Ptr XsdComplexType::contentType() const +{ + return m_contentType; +} + +void XsdComplexType::setAttributeUses(const XsdAttributeUse::List &attributeUses) +{ + m_attributeUses = attributeUses; +} + +void XsdComplexType::addAttributeUse(const XsdAttributeUse::Ptr &attributeUse) +{ + m_attributeUses.append(attributeUse); +} + +XsdAttributeUse::List XsdComplexType::attributeUses() const +{ + return m_attributeUses; +} + +void XsdComplexType::setAttributeWildcard(const XsdWildcard::Ptr &wildcard) +{ + m_attributeWildcard = wildcard; +} + +XsdWildcard::Ptr XsdComplexType::attributeWildcard() const +{ + return m_attributeWildcard; +} + +XsdComplexType::TypeCategory XsdComplexType::category() const +{ + return ComplexType; +} + +void XsdComplexType::setDerivationMethod(DerivationMethod method) +{ + m_derivationMethod = method; +} + +XsdComplexType::DerivationMethod XsdComplexType::derivationMethod() const +{ + return m_derivationMethod; +} + +void XsdComplexType::setProhibitedSubstitutions(const BlockingConstraints &substitutions) +{ + m_prohibitedSubstitutions = substitutions; +} + +XsdComplexType::BlockingConstraints XsdComplexType::prohibitedSubstitutions() const +{ + return m_prohibitedSubstitutions; +} + +void XsdComplexType::setAssertions(const XsdAssertion::List &assertions) +{ + m_assertions = assertions; +} + +void XsdComplexType::addAssertion(const XsdAssertion::Ptr &assertion) +{ + m_assertions.append(assertion); +} + +XsdAssertion::List XsdComplexType::assertions() const +{ + return m_assertions; +} + +bool XsdComplexType::isDefinedBySchema() const +{ + return true; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdcomplextype_p.h b/src/xmlpatterns/schema/qxsdcomplextype_p.h new file mode 100644 index 0000000..078c8f0 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdcomplextype_p.h @@ -0,0 +1,374 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdComplexType_H +#define Patternist_XsdComplexType_H + +#include "qanytype_p.h" +#include "qxsdassertion_p.h" +#include "qxsdattributeuse_p.h" +#include "qxsdparticle_p.h" +#include "qxsdsimpletype_p.h" +#include "qxsduserschematype_p.h" +#include "qxsdwildcard_p.h" + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Represents a XSD complexType object. + * + * This class represents the complexType object of a XML schema as described + * here. + * + * It contains information from either a top-level complex type declaration (as child of a schema object) + * or a local complex type declaration (as descendant of an element object). + * + * @see XML Schema API reference + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdComplexType : public XsdUserSchemaType + { + public: + typedef QExplicitlySharedDataPointer Ptr; + + /** + * @short Describes the open content object of a complex type. + * + * @see Open Content Definition + */ + class OpenContent : public QSharedData, public XsdAnnotated + { + public: + typedef QExplicitlySharedDataPointer Ptr; + + /** + * Describes the mode of the open content. + * + * @see Mode Definition + */ + enum Mode + { + None, + Interleave, + Suffix + }; + + /** + * Sets the @p mode of the open content. + * + * @see Mode Definition + */ + void setMode(Mode mode); + + /** + * Returns the mode of the open content. + */ + Mode mode() const; + + /** + * Sets the @p wildcard of the open content. + * + * @see Wildcard Definition + */ + void setWildcard(const XsdWildcard::Ptr &wildcard); + + /** + * Returns the wildcard of the open content. + */ + XsdWildcard::Ptr wildcard() const; + + private: + Mode m_mode; + XsdWildcard::Ptr m_wildcard; + }; + + /** + * @short Describes the content type of a complex type. + */ + class ContentType : public QSharedData + { + public: + typedef QExplicitlySharedDataPointer Ptr; + + /** + * Describes the variety of the content type. + */ + enum Variety + { + Empty = 0, ///< The complex type has no further content. + Simple, ///< The complex type has only simple type content (e.g. text, number etc.) + ElementOnly, ///< The complex type has further elements or attributes but no text as content. + Mixed ///< The complex type has further elements or attributes and text as content. + }; + + /** + * Sets the @p variety of the content type. + * + * @see Variety Definition + */ + void setVariety(Variety variety); + + /** + * Returns the variety of the content type. + */ + Variety variety() const; + + /** + * Sets the @p particle object of the content type. + * + * The content type has only a particle object if + * its variety is ElementOnly or Mixed. + * + * @see XsdParticle + * @see Particle Declaration + */ + void setParticle(const XsdParticle::Ptr &particle); + + /** + * Returns the particle object of the content type, + * or an empty pointer if its variety is neither + * ElementOnly nor Mixed. + */ + XsdParticle::Ptr particle() const; + + /** + * Sets the open @p content object of the content type. + * + * The content type has only an open content object if + * its variety is ElementOnly or Mixed. + * + * @see OpenContent + * @see Open Content Declaration + */ + void setOpenContent(const OpenContent::Ptr &content); + + /** + * Returns the open content object of the content type, + * or an empty pointer if its variety is neither + * ElementOnly nor Mixed. + */ + OpenContent::Ptr openContent() const; + + /** + * Sets the simple @p type object of the content type. + * + * The content type has only a simple type object if + * its variety is Simple. + * + * @see Simple Type Definition + */ + void setSimpleType(const AnySimpleType::Ptr &type); + + /** + * Returns the simple type object of the content type, + * or an empty pointer if its variety is not Simple. + */ + AnySimpleType::Ptr simpleType() const; + + private: + Variety m_variety; + XsdParticle::Ptr m_particle; + OpenContent::Ptr m_openContent; + XsdSimpleType::Ptr m_simpleType; + }; + + + /** + * Creates a complex type object with empty content. + */ + XsdComplexType(); + + /** + * Destroys the complex type object. + */ + ~XsdComplexType() {}; + + /** + * Returns the display name of the complex type. + * + * The display name can be used to show the type name + * to the user. + * + * @param namePool The name pool where the type name is stored in. + */ + virtual QString displayName(const NamePool::Ptr &namePool) const; + + /** + * Sets the base type of the complex type. + * + * @see Base Type Definition + */ + void setWxsSuperType(const SchemaType::Ptr &type); + + /** + * Returns the base type of the complex type. + */ + virtual SchemaType::Ptr wxsSuperType() const; + + /** + * Sets the context @p component of the complex type. + * + * The component is either an element declaration or a complex type definition. + */ + void setContext(const NamedSchemaComponent::Ptr &component); + + /** + * Returns the context component of the complex type. + */ + NamedSchemaComponent::Ptr context() const; + + /** + * Sets the derivation @p method of the complex type. + * + * The derivation method depends on whether the complex + * type object has an extension or restriction object as child. + * + * @see Derivation Method Definition + * @see DerivationMethod + */ + void setDerivationMethod(DerivationMethod method); + + /** + * Returns the derivation method of the complex type. + */ + virtual DerivationMethod derivationMethod() const; + + /** + * Sets whether the complex type is @p abstract. + * + * @see Abstract Definition + */ + void setIsAbstract(bool abstract); + + /** + * Returns whether the complex type is abstract. + */ + virtual bool isAbstract() const; + + /** + * Sets the list of all attribute @p uses of the complex type. + * + * @see Attribute Uses Declaration + */ + void setAttributeUses(const XsdAttributeUse::List &uses); + + /** + * Adds a new attribute @p use to the complex type. + */ + void addAttributeUse(const XsdAttributeUse::Ptr &use); + + /** + * Returns the list of all attribute uses of the complex type. + */ + XsdAttributeUse::List attributeUses() const; + + /** + * Sets the attribute @p wildcard of the complex type. + * + * @see Attribute Wildcard Declaration + */ + void setAttributeWildcard(const XsdWildcard::Ptr &wildcard); + + /** + * Returns the attribute wildcard of the complex type. + */ + XsdWildcard::Ptr attributeWildcard() const; + + /** + * Always returns SchemaType::ComplexType + */ + virtual TypeCategory category() const; + + /** + * Sets the content @p type of the complex type. + * + * @see ContentType + */ + void setContentType(const ContentType::Ptr &type); + + /** + * Returns the content type of the complex type. + */ + ContentType::Ptr contentType() const; + + /** + * Sets the prohibited @p substitutions of the complex type. + * + * Only ExtensionConstraint and RestrictionConstraint are allowed. + * + * @see Prohibited Substitutions Definition + */ + void setProhibitedSubstitutions(const BlockingConstraints &substitutions); + + /** + * Returns the prohibited substitutions of the complex type. + */ + BlockingConstraints prohibitedSubstitutions() const; + + /** + * Sets the @p assertions of the complex type. + * + * @see Assertions Definition + */ + void setAssertions(const XsdAssertion::List &assertions); + + /** + * Adds an @p assertion to the complex type. + * + * @see Assertions Definition + */ + void addAssertion(const XsdAssertion::Ptr &assertion); + + /** + * Returns the assertions of the complex type. + */ + XsdAssertion::List assertions() const; + + /** + * Always returns @c true. + */ + virtual bool isDefinedBySchema() const; + + private: + SchemaType::Ptr m_superType; + NamedSchemaComponent::Ptr m_context; + DerivationMethod m_derivationMethod; + bool m_isAbstract; + XsdAttributeUse::List m_attributeUses; + XsdWildcard::Ptr m_attributeWildcard; + ContentType::Ptr m_contentType; + BlockingConstraints m_prohibitedSubstitutions; + XsdAssertion::List m_assertions; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsddocumentation.cpp b/src/xmlpatterns/schema/qxsddocumentation.cpp new file mode 100644 index 0000000..4994143 --- /dev/null +++ b/src/xmlpatterns/schema/qxsddocumentation.cpp @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qxsddocumentation_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +XsdDocumentation::XsdDocumentation() +{ +} + +XsdDocumentation::~XsdDocumentation() +{ +} + +void XsdDocumentation::setSource(const AnyURI::Ptr &source) +{ + m_source = source; +} + +AnyURI::Ptr XsdDocumentation::source() const +{ + return m_source; +} + +void XsdDocumentation::setLanguage(const DerivedString::Ptr &language) +{ + m_language = language; +} + +DerivedString::Ptr XsdDocumentation::language() const +{ + return m_language; +} + +void XsdDocumentation::setContent(const QString &content) +{ + m_content = content; +} + +QString XsdDocumentation::content() const +{ + return m_content; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsddocumentation_p.h b/src/xmlpatterns/schema/qxsddocumentation_p.h new file mode 100644 index 0000000..c44a2bb --- /dev/null +++ b/src/xmlpatterns/schema/qxsddocumentation_p.h @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdDocumentation_H +#define Patternist_XsdDocumentation_H + +#include "qanytype_p.h" +#include "qanyuri_p.h" +#include "qderivedstring_p.h" +#include "qnamedschemacomponent_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Represents a XSD documentation object. + * + * This class represents the documentation component of an annotation object + * of a XML schema as described here. + * + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdDocumentation : public NamedSchemaComponent + { + public: + typedef QExplicitlySharedDataPointer Ptr; + typedef QList List; + + /** + * Creates a new documentation object. + */ + XsdDocumentation(); + + /** + * Destroys the documentation object. + */ + ~XsdDocumentation(); + + /** + * Sets the @p source of the documentation. + * + * The source points to an URL that contains more + * information. + */ + void setSource(const AnyURI::Ptr &source); + + /** + * Returns the source of the documentation. + */ + AnyURI::Ptr source() const; + + /** + * Sets the @p language of the documentation. + */ + void setLanguage(const DerivedString::Ptr &language); + + /** + * Returns the language of the documentation. + */ + DerivedString::Ptr language() const; + + /** + * Sets the @p content of the documentation. + * + * The content can be of abritrary type. + */ + void setContent(const QString &content); + + /** + * Returns the content of the documentation. + */ + QString content() const; + + private: + AnyURI::Ptr m_source; + DerivedString::Ptr m_language; + QString m_content; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsdelement.cpp b/src/xmlpatterns/schema/qxsdelement.cpp new file mode 100644 index 0000000..2b8ccab --- /dev/null +++ b/src/xmlpatterns/schema/qxsdelement.cpp @@ -0,0 +1,214 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qxsdelement_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +void XsdElement::Scope::setVariety(Variety variety) +{ + m_variety = variety; +} + +XsdElement::Scope::Variety XsdElement::Scope::variety() const +{ + return m_variety; +} + +void XsdElement::Scope::setParent(const NamedSchemaComponent::Ptr &parent) +{ + m_parent = parent; +} + +NamedSchemaComponent::Ptr XsdElement::Scope::parent() const +{ + return m_parent; +} + +void XsdElement::ValueConstraint::setVariety(Variety variety) +{ + m_variety = variety; +} + +XsdElement::ValueConstraint::Variety XsdElement::ValueConstraint::variety() const +{ + return m_variety; +} + +void XsdElement::ValueConstraint::setValue(const QString &value) +{ + m_value = value; +} + +QString XsdElement::ValueConstraint::value() const +{ + return m_value; +} + +void XsdElement::ValueConstraint::setLexicalForm(const QString &form) +{ + m_lexicalForm = form; +} + +QString XsdElement::ValueConstraint::lexicalForm() const +{ + return m_lexicalForm; +} + +void XsdElement::TypeTable::addAlternative(const XsdAlternative::Ptr &alternative) +{ + m_alternatives.append(alternative); +} + +XsdAlternative::List XsdElement::TypeTable::alternatives() const +{ + return m_alternatives; +} + +void XsdElement::TypeTable::setDefaultTypeDefinition(const XsdAlternative::Ptr &type) +{ + m_defaultTypeDefinition = type; +} + +XsdAlternative::Ptr XsdElement::TypeTable::defaultTypeDefinition() const +{ + return m_defaultTypeDefinition; +} + + +XsdElement::XsdElement() + : m_isAbstract(false) +{ +} + +bool XsdElement::isElement() const +{ + return true; +} + +void XsdElement::setType(const SchemaType::Ptr &type) +{ + m_type = type; +} + +SchemaType::Ptr XsdElement::type() const +{ + return m_type; +} + +void XsdElement::setScope(const Scope::Ptr &scope) +{ + m_scope = scope; +} + +XsdElement::Scope::Ptr XsdElement::scope() const +{ + return m_scope; +} + +void XsdElement::setValueConstraint(const ValueConstraint::Ptr &constraint) +{ + m_valueConstraint = constraint; +} + +XsdElement::ValueConstraint::Ptr XsdElement::valueConstraint() const +{ + return m_valueConstraint; +} + +void XsdElement::setTypeTable(const TypeTable::Ptr &table) +{ + m_typeTable = table; +} + +XsdElement::TypeTable::Ptr XsdElement::typeTable() const +{ + return m_typeTable; +} + +void XsdElement::setIsAbstract(bool abstract) +{ + m_isAbstract = abstract; +} + +bool XsdElement::isAbstract() const +{ + return m_isAbstract; +} + +void XsdElement::setIsNillable(bool nillable) +{ + m_isNillable = nillable; +} + +bool XsdElement::isNillable() const +{ + return m_isNillable; +} + +void XsdElement::setDisallowedSubstitutions(const BlockingConstraints &substitutions) +{ + m_disallowedSubstitutions = substitutions; +} + +XsdElement::BlockingConstraints XsdElement::disallowedSubstitutions() const +{ + return m_disallowedSubstitutions; +} + +void XsdElement::setSubstitutionGroupExclusions(const SchemaType::DerivationConstraints &exclusions) +{ + m_substitutionGroupExclusions = exclusions; +} + +SchemaType::DerivationConstraints XsdElement::substitutionGroupExclusions() const +{ + return m_substitutionGroupExclusions; +} + +void XsdElement::setIdentityConstraints(const XsdIdentityConstraint::List &constraints) +{ + m_identityConstraints = constraints; +} + +void XsdElement::addIdentityConstraint(const XsdIdentityConstraint::Ptr &constraint) +{ + m_identityConstraints.append(constraint); +} + +XsdIdentityConstraint::List XsdElement::identityConstraints() const +{ + return m_identityConstraints; +} + +void XsdElement::setSubstitutionGroupAffiliations(const XsdElement::List &affiliations) +{ + m_substitutionGroupAffiliations = affiliations; +} + +XsdElement::List XsdElement::substitutionGroupAffiliations() const +{ + return m_substitutionGroupAffiliations; +} + +void XsdElement::addSubstitutionGroup(const XsdElement::Ptr &element) +{ + m_substitutionGroups.insert(element); +} + +XsdElement::List XsdElement::substitutionGroups() const +{ + return m_substitutionGroups.toList(); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdelement_p.h b/src/xmlpatterns/schema/qxsdelement_p.h new file mode 100644 index 0000000..e571687 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdelement_p.h @@ -0,0 +1,373 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdElement_H +#define Patternist_XsdElement_H + +#include "qschemacomponent_p.h" +#include "qschematype_p.h" +#include "qxsdalternative_p.h" +#include "qxsdidentityconstraint_p.h" +#include "qxsdcomplextype_p.h" + +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Represents a XSD element object. + * + * This class represents the element object of a XML schema as described + * here. + * + * It contains information from either a top-level element declaration (as child of a schema object) + * or a local element declaration (as descendant of an complexType object). + * + * @see XML Schema API reference + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdElement : public XsdTerm + { + public: + typedef QExplicitlySharedDataPointer Ptr; + typedef QList List; + + + /** + * Describes the constraint type of the element. + */ + enum ConstraintType + { + NoneConstraint, ///< The value of the element has no constraints. + DefaultConstraint, ///< The element has a default value set. + FixedConstraint ///< The element has a fixed value set. + }; + + /** + * Describes the scope of an element. + * + * @see Scope Definition + */ + class Scope : public QSharedData + { + public: + typedef QExplicitlySharedDataPointer Ptr; + + /** + * Describes the scope of an attribute. + */ + enum Variety + { + Global, ///< The element is defined globally as child of the schema object. + Local ///< The element is defined locally as child of a complex type or model group definition. + }; + + /** + * Sets the @p variety of the element scope. + */ + void setVariety(Variety variety); + + /** + * Returns the variety of the element scope. + */ + Variety variety() const; + + /** + * Sets the @p parent complex type or model group definition of the element scope. + */ + void setParent(const NamedSchemaComponent::Ptr &parent); + + /** + * Returns the parent complex type or model group definition of the element scope. + */ + NamedSchemaComponent::Ptr parent() const; + + private: + Variety m_variety; + NamedSchemaComponent::Ptr m_parent; + }; + + /** + * Describes a type table of an element. + * + * @see Type Table Definition + */ + class TypeTable : public QSharedData + { + public: + typedef QExplicitlySharedDataPointer Ptr; + + /** + * Adds an @p alternative to the type table. + */ + void addAlternative(const XsdAlternative::Ptr &alternative); + + /** + * Returns the alternatives of the type table. + */ + XsdAlternative::List alternatives() const; + + /** + * Sets the default @p type definition. + */ + void setDefaultTypeDefinition(const XsdAlternative::Ptr &type); + + /** + * Returns the default type definition. + */ + XsdAlternative::Ptr defaultTypeDefinition() const; + + private: + XsdAlternative::List m_alternatives; + XsdAlternative::Ptr m_defaultTypeDefinition; + }; + + + /** + * Describes the value constraint of an element. + * + * @see Value Constraint Definition + */ + class ValueConstraint : public QSharedData + { + public: + typedef QExplicitlySharedDataPointer Ptr; + + /** + * Describes the value constraint of an element. + */ + enum Variety + { + Default, ///< The element has a default value set. + Fixed ///< The element has a fixed value set. + }; + + /** + * Sets the @p variety of the element value constraint. + */ + void setVariety(Variety variety); + + /** + * Returns the variety of the element value constraint. + */ + Variety variety() const; + + /** + * Sets the @p value of the constraint. + */ + void setValue(const QString &value); + + /** + * Returns the value of the constraint. + */ + QString value() const; + + /** + * Sets the lexical @p form of the constraint. + */ + void setLexicalForm(const QString &form); + + /** + * Returns the lexical form of the constraint. + */ + QString lexicalForm() const; + + private: + Variety m_variety; + QString m_value; + QString m_lexicalForm; + }; + + /** + * Creates a new element object. + */ + XsdElement(); + + /** + * Always returns @c true, used to avoid dynamic casts. + */ + virtual bool isElement() const; + + /** + * Sets the @p type of the element. + * + * @see Type Definition + */ + void setType(const SchemaType::Ptr &type); + + /** + * Returns the type of the element. + */ + SchemaType::Ptr type() const; + + /** + * Sets the @p scope of the element. + * + * @see Scope Definition + */ + void setScope(const Scope::Ptr &scope); + + /** + * Returns the scope of the element. + */ + Scope::Ptr scope() const; + + /** + * Sets the value @p constraint of the element. + * + * @see Value Constraint Definition + */ + void setValueConstraint(const ValueConstraint::Ptr &constraint); + + /** + * Returns the value constraint of the element. + */ + ValueConstraint::Ptr valueConstraint() const; + + /** + * Sets the type table of the element. + * + * @see Type Table Definition + */ + void setTypeTable(const TypeTable::Ptr &table); + + /** + * Returns the type table of the element. + */ + TypeTable::Ptr typeTable() const; + + /** + * Sets whether the element is @p abstract. + * + * @see Abstract Definition + */ + void setIsAbstract(bool abstract); + + /** + * Returns whether the element is abstract. + */ + bool isAbstract() const; + + /** + * Sets whether the element is @p nillable. + * + * @see Nillable Definition + */ + void setIsNillable(bool nillable); + + /** + * Returns whether the element is nillable. + */ + bool isNillable() const; + + /** + * Sets the disallowed @p substitutions of the element. + * + * Only ExtensionConstraint, RestrictionConstraint and SubstitutionConstraint are allowed. + * + * @see Disallowed Substitutions Definition + */ + void setDisallowedSubstitutions(const BlockingConstraints &substitutions); + + /** + * Returns the disallowed substitutions of the element. + */ + BlockingConstraints disallowedSubstitutions() const; + + /** + * Sets the substitution group @p exclusions of the element. + * + * Only SchemaType::ExtensionConstraint and SchemaType::RestrictionConstraint are allowed. + * + * @see Substitution Group Exclusions Definition + */ + void setSubstitutionGroupExclusions(const SchemaType::DerivationConstraints &exclusions); + + /** + * Returns the substitution group exclusions of the element. + */ + SchemaType::DerivationConstraints substitutionGroupExclusions() const; + + /** + * Sets the identity @p constraints of the element. + * + * @see Identity Constraint Definition + */ + void setIdentityConstraints(const XsdIdentityConstraint::List &constraints); + + /** + * Adds a new identity @p constraint to the element. + */ + void addIdentityConstraint(const XsdIdentityConstraint::Ptr &constraint); + + /** + * Returns a list of all identity constraints of the element. + */ + XsdIdentityConstraint::List identityConstraints() const; + + /** + * Sets the substitution group @p affiliations of the element. + * + * @see Substitution Group Affiliations + */ + void setSubstitutionGroupAffiliations(const XsdElement::List &affiliations); + + /** + * Returns the substitution group affiliations of the element. + */ + XsdElement::List substitutionGroupAffiliations() const; + + /** + * Adds a substitution group to the element. + */ + void addSubstitutionGroup(const XsdElement::Ptr &elements); + + /** + * Returns the substitution groups of the element. + */ + XsdElement::List substitutionGroups() const; + + private: + SchemaType::Ptr m_type; + Scope::Ptr m_scope; + ValueConstraint::Ptr m_valueConstraint; + TypeTable::Ptr m_typeTable; + bool m_isAbstract; + bool m_isNillable; + BlockingConstraints m_disallowedSubstitutions; + SchemaType::DerivationConstraints m_substitutionGroupExclusions; + XsdIdentityConstraint::List m_identityConstraints; + XsdElement::List m_substitutionGroupAffiliations; + QSet m_substitutionGroups; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsdfacet.cpp b/src/xmlpatterns/schema/qxsdfacet.cpp new file mode 100644 index 0000000..513eee8 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdfacet.cpp @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qxsdfacet_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +XsdFacet::XsdFacet() + : m_type(None) +{ +} + +void XsdFacet::setType(Type type) +{ + m_type = type; +} + +XsdFacet::Type XsdFacet::type() const +{ + return m_type; +} + +void XsdFacet::setValue(const AtomicValue::Ptr &value) +{ + m_value = value; +} + +AtomicValue::Ptr XsdFacet::value() const +{ + return m_value; +} + +void XsdFacet::setMultiValue(const AtomicValue::List &value) +{ + m_multiValue = value; +} + +AtomicValue::List XsdFacet::multiValue() const +{ + return m_multiValue; +} + +void XsdFacet::setAssertions(const XsdAssertion::List &assertions) +{ + m_assertions = assertions; +} + +XsdAssertion::List XsdFacet::assertions() const +{ + return m_assertions; +} + +void XsdFacet::setFixed(bool fixed) +{ + m_fixed = fixed; +} + +bool XsdFacet::fixed() const +{ + return m_fixed; +} + +QString XsdFacet::typeName(Type type) +{ + switch (type) { + case Length: return QLatin1String("length"); break; + case MinimumLength: return QLatin1String("minLength"); break; + case MaximumLength: return QLatin1String("maxLength"); break; + case Pattern: return QLatin1String("pattern"); break; + case WhiteSpace: return QLatin1String("whiteSpace"); break; + case MaximumInclusive: return QLatin1String("maxInclusive"); break; + case MaximumExclusive: return QLatin1String("maxExclusive"); break; + case MinimumInclusive: return QLatin1String("minInclusive"); break; + case MinimumExclusive: return QLatin1String("minExclusive"); break; + case TotalDigits: return QLatin1String("totalDigits"); break; + case FractionDigits: return QLatin1String("fractionDigits"); break; + case Enumeration: return QLatin1String("enumeration"); break; + case Assertion: return QLatin1String("assertion"); break; + case None: // fall through + default: return QLatin1String("none"); break; + } +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdfacet_p.h b/src/xmlpatterns/schema/qxsdfacet_p.h new file mode 100644 index 0000000..f1f8110 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdfacet_p.h @@ -0,0 +1,183 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdFacet_H +#define Patternist_XsdFacet_H + +#include "qitem_p.h" +#include "qnamedschemacomponent_p.h" +#include "qxsdannotated_p.h" +#include "qxsdassertion_p.h" + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Represents a XSD facet object. + * + * This class represents one of the following XML schema objects: + * + * + * + * @see XML Schema API reference + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdFacet : public NamedSchemaComponent, public XsdAnnotated + { + public: + typedef QExplicitlySharedDataPointer Ptr; + + /** + * Describes the type of the facet. + */ + enum Type + { + None = 0, ///< An invalid facet. + Length = 1 << 0, ///< Match the exact length (Length Definition) + MinimumLength = 1 << 1, ///< Match the minimum length (Minimum Length Definition) + MaximumLength = 1 << 2, ///< Match the maximum length (Maximum Length Definition) + Pattern = 1 << 3, ///< Match a regular expression (Pattern Definition) + WhiteSpace = 1 << 4, ///< Match a whitespace rule (White Space Definition) + MaximumInclusive = 1 << 5, ///< Match a maximum inclusive (Maximum Inclusive Definition) + MaximumExclusive = 1 << 6, ///< Match a maximum exclusive (Maximum Exclusive Definition) + MinimumInclusive = 1 << 7, ///< Match a minimum inclusive (Minimum Inclusive Definition) + MinimumExclusive = 1 << 8, ///< Match a minimum exclusive (Minimum Exclusive Definition) + TotalDigits = 1 << 9, ///< Match some integer digits (Total Digits Definition) + FractionDigits = 1 << 10, ///< Match some double digits (Fraction Digits Definition) + Enumeration = 1 << 11, ///< Match an enumeration (Enumeration Definition) + Assertion = 1 << 12, ///< Match an assertion (Assertion Definition) + }; + typedef QHash Hash; + typedef QHashIterator HashIterator; + + /** + * Creates a new facet object of type None. + */ + XsdFacet(); + + /** + * Sets the @p type of the facet. + * + * @see Type + */ + void setType(Type type); + + /** + * Returns the type of the facet. + */ + Type type() const; + + /** + * Sets the @p value of the facet. + * + * Depending on the type of the facet the + * value can be a string, interger, double etc. + * + * @note This method should be used for all types of facets + * except Pattern, Enumeration and Assertion. + */ + void setValue(const AtomicValue::Ptr &value); + + /** + * Returns the value of the facet or an empty pointer if facet + * type is Pattern, Enumeration or Assertion. + */ + AtomicValue::Ptr value() const; + + /** + * Sets the @p value of the facet. + * + * @note This method should be used for if the type of the + * facet is Pattern or Enumeration. + */ + void setMultiValue(const AtomicValue::List &value); + + /** + * Returns the value of the facet or an empty pointer if facet + * type is not of type Pattern or Enumeration. + */ + AtomicValue::List multiValue() const; + + /** + * Sets the @p assertions of the facet. + * + * @note This method should be used if the type of the + * facet is Assertion. + */ + void setAssertions(const XsdAssertion::List &assertions); + + /** + * Returns the assertions of the facet or an empty pointer if facet + * type is not of type Assertion. + */ + XsdAssertion::List assertions() const; + + /** + * Sets whether the facet is @p fixed. + * + * All facets except pattern, enumeration and assertion can be fixed. + */ + void setFixed(bool fixed); + + /** + * Returns whether the facet is fixed. + */ + bool fixed() const; + + /** + * Returns the textual description of the facet @p type. + */ + static QString typeName(Type type); + + private: + Type m_type; + AtomicValue::Ptr m_value; + AtomicValue::List m_multiValue; + XsdAssertion::List m_assertions; + bool m_fixed; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsdidcache.cpp b/src/xmlpatterns/schema/qxsdidcache.cpp new file mode 100644 index 0000000..d4a7b64 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdidcache.cpp @@ -0,0 +1,36 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qxsdidcache_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +void XsdIdCache::addId(const QString &id) +{ + const QWriteLocker locker(&m_lock); + Q_ASSERT(!m_ids.contains(id)); + + m_ids.insert(id); +} + +bool XsdIdCache::hasId(const QString &id) const +{ + const QReadLocker locker(&m_lock); + + return m_ids.contains(id); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdidcache_p.h b/src/xmlpatterns/schema/qxsdidcache_p.h new file mode 100644 index 0000000..b1d3c0f --- /dev/null +++ b/src/xmlpatterns/schema/qxsdidcache_p.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdIdCache_H +#define Patternist_XsdIdCache_H + +#include "qschemacomponent_p.h" + +#include +#include +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Helper class for keeping track of all existing IDs in a schema. + * + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdIdCache : public QSharedData + { + public: + typedef QExplicitlySharedDataPointer Ptr; + + /** + * Adds an @p id to the id cache. + */ + void addId(const QString &id); + + /** + * Returns whether the id cache contains the given @p id already. + */ + bool hasId(const QString &id) const; + + private: + QSet m_ids; + mutable QReadWriteLock m_lock; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsdidchelper.cpp b/src/xmlpatterns/schema/qxsdidchelper.cpp new file mode 100644 index 0000000..70980cb --- /dev/null +++ b/src/xmlpatterns/schema/qxsdidchelper.cpp @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qxsdidchelper_p.h" + +#include "qderivedstring_p.h" +#include "qxsdschemahelper_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +FieldNode::FieldNode() +{ +} + +FieldNode::FieldNode(const QXmlItem &item, const QString &data, const SchemaType::Ptr &type) + : m_item(item) + , m_data(data) + , m_type(type) +{ +} + +bool FieldNode::isEmpty() const +{ + return m_item.isNull(); +} + +bool FieldNode::isEqualTo(const FieldNode &other, const NamePool::Ptr &namePool, const ReportContext::Ptr &context, const SourceLocationReflection *const reflection) const +{ + if (m_type != other.m_type) + return false; + + const DerivedString::Ptr string = DerivedString::fromLexical(namePool, m_data); + const DerivedString::Ptr otherString = DerivedString::fromLexical(namePool, other.m_data); + + return XsdSchemaHelper::constructAndCompare(string, AtomicComparator::OperatorEqual, otherString, m_type, context, reflection); +} + +QXmlItem FieldNode::item() const +{ + return m_item; +} + +TargetNode::TargetNode(const QXmlItem &item) + : m_item(item) +{ +} + +QXmlItem TargetNode::item() const +{ + return m_item; +} + +QVector TargetNode::fieldItems() const +{ + QVector items; + + for (int i = 0; i < m_fields.count(); ++i) + items.append(m_fields.at(i).item()); + + return items; +} + +int TargetNode::emptyFieldsCount() const +{ + int counter = 0; + for (int i = 0; i < m_fields.count(); ++i) { + if (m_fields.at(i).isEmpty()) + ++counter; + } + + return counter; +} + +bool TargetNode::fieldsAreEqual(const TargetNode &other, const NamePool::Ptr &namePool, const ReportContext::Ptr &context, const SourceLocationReflection *const reflection) const +{ + if (m_fields.count() != other.m_fields.count()) + return false; + + for (int i = 0; i < m_fields.count(); ++i) { + if (!m_fields.at(i).isEqualTo(other.m_fields.at(i), namePool, context, reflection)) + return false; + } + + return true; +} + +void TargetNode::addField(const QXmlItem &item, const QString &data, const SchemaType::Ptr &type) +{ + m_fields.append(FieldNode(item, data, type)); +} + +bool TargetNode::operator==(const TargetNode &other) const +{ + return (m_item.toNodeModelIndex() == other.m_item.toNodeModelIndex()); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdidchelper_p.h b/src/xmlpatterns/schema/qxsdidchelper_p.h new file mode 100644 index 0000000..3034292 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdidchelper_p.h @@ -0,0 +1,156 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdIdcHelper_H +#define Patternist_XsdIdcHelper_H + +#include "qreportcontext_p.h" +#include "qschematype_p.h" + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + + /** + * @short A helper class for validating identity constraints. + * + * This class represents a field node from the key-sequence as defined in + * the validation rules at http://www.w3.org/TR/xmlschema11-1/#d0e32243. + */ + class FieldNode + { + public: + /** + * Creates an empty field node. + */ + FieldNode(); + + /** + * Creates a field node that is bound to a xml node. + * + * @param item The xml node the field is bound to. + * @param data The string content of that field. + * @param type The type that is bound to that field. + */ + FieldNode(const QXmlItem &item, const QString &data, const SchemaType::Ptr &type); + + /** + * Returns whether this field is empty. + * + * A field can be empty, if the xpath expression selects an absent attribute + * or element. + */ + bool isEmpty() const; + + /** + * Returns whether this field is equal to the @p other field. + * + * Equal means that both have the same type and there content is equal in the + * types value space. + */ + bool isEqualTo(const FieldNode &other, const NamePool::Ptr &namePool, const ReportContext::Ptr &context, const SourceLocationReflection *const reflection) const; + + /** + * Returns the xml node item the field is bound to. + */ + QXmlItem item() const; + + private: + QXmlItem m_item; + QString m_data; + SchemaType::Ptr m_type; + }; + + /** + * @short A helper class for validating identity constraints. + * + * This class represents a target or qualified node from the target or qualified + * node set as defined in the validation rules at http://www.w3.org/TR/xmlschema11-1/#d0e32243. + * + * A target node is part of the qualified node set, if all of its fields are not empty. + */ + class TargetNode + { + public: + /** + * Defines a set of target nodes. + */ + typedef QSet Set; + + /** + * Creates a new target node that is bound to the xml node @p item. + */ + explicit TargetNode(const QXmlItem &item); + + /** + * Returns the xml node item the target node is bound to. + */ + QXmlItem item() const; + + /** + * Returns all xml node items, the fields of that target node are bound to. + */ + QVector fieldItems() const; + + /** + * Returns the number of fields that are empty. + */ + int emptyFieldsCount() const; + + /** + * Returns whether the target node has the same fields as the @p other target node. + */ + bool fieldsAreEqual(const TargetNode &other, const NamePool::Ptr &namePool, const ReportContext::Ptr &context, const SourceLocationReflection *const reflection) const; + + /** + * Adds a new field to the target node with the given values. + */ + void addField(const QXmlItem &item, const QString &data, const SchemaType::Ptr &type); + + /** + * Returns whether the target node is equal to the @p other target node. + */ + bool operator==(const TargetNode &other) const; + + private: + QXmlItem m_item; + QVector m_fields; + }; + + /** + * Creates a hash value for the given target @p node. + */ + inline uint qHash(const QPatternist::TargetNode &node) + { + return qHash(node.item().toNodeModelIndex()); + } +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsdidentityconstraint.cpp b/src/xmlpatterns/schema/qxsdidentityconstraint.cpp new file mode 100644 index 0000000..e72a005 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdidentityconstraint.cpp @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qxsdidentityconstraint_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +void XsdIdentityConstraint::setCategory(Category category) +{ + m_category = category; +} + +XsdIdentityConstraint::Category XsdIdentityConstraint::category() const +{ + return m_category; +} + +void XsdIdentityConstraint::setSelector(const XsdXPathExpression::Ptr &selector) +{ + m_selector = selector; +} + +XsdXPathExpression::Ptr XsdIdentityConstraint::selector() const +{ + return m_selector; +} + +void XsdIdentityConstraint::setFields(const XsdXPathExpression::List &fields) +{ + m_fields = fields; +} + +void XsdIdentityConstraint::addField(const XsdXPathExpression::Ptr &field) +{ + m_fields.append(field); +} + +XsdXPathExpression::List XsdIdentityConstraint::fields() const +{ + return m_fields; +} + +void XsdIdentityConstraint::setReferencedKey(const XsdIdentityConstraint::Ptr &referencedKey) +{ + m_referencedKey = referencedKey; +} + +XsdIdentityConstraint::Ptr XsdIdentityConstraint::referencedKey() const +{ + return m_referencedKey; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdidentityconstraint_p.h b/src/xmlpatterns/schema/qxsdidentityconstraint_p.h new file mode 100644 index 0000000..6870b1e --- /dev/null +++ b/src/xmlpatterns/schema/qxsdidentityconstraint_p.h @@ -0,0 +1,143 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdIdentityConstraint_H +#define Patternist_XsdIdentityConstraint_H + +#include "qnamedschemacomponent_p.h" +#include "qxsdannotated_p.h" +#include "qxsdxpathexpression_p.h" + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Represents a XSD identity constraint object. + * + * This class represents the identity constraint object of a XML schema as described + * here. + * + * It contains information from either a key object, a keyref object or an + * unique object. + * + * @see XML Schema API reference + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdIdentityConstraint : public NamedSchemaComponent, public XsdAnnotated + { + public: + typedef QExplicitlySharedDataPointer Ptr; + typedef QList List; + + /** + * Describes the category of the identity constraint. + */ + enum Category + { + Key = 1, ///< The constraint is a key constraint + KeyReference, ///< The constraint is a keyref constraint + Unique ///< The constraint is an unique constraint + }; + + /** + * Sets the @p category of the identity constraint. + * + * @see Category + */ + void setCategory(Category category); + + /** + * Returns the category of the identity constraint. + */ + Category category() const; + + /** + * Sets the @p selector of the identity constraint. + * + * The selector is a restricted XPath 1.0 expression, + * that selects a set of nodes. + * + * @see + */ + void setSelector(const XsdXPathExpression::Ptr &selector); + + /** + * Returns the selector of the identity constraint. + */ + XsdXPathExpression::Ptr selector() const; + + /** + * Sets the @p fields of the identity constraint. + * + * Each field is a restricted XPath 1.0 expression, + * that selects a set of nodes. + * + * @see + */ + void setFields(const XsdXPathExpression::List &fields); + + /** + * Adds a new @p field to the identity constraint. + */ + void addField(const XsdXPathExpression::Ptr &field); + + /** + * Returns all fields of the identity constraint. + */ + XsdXPathExpression::List fields() const; + + /** + * Sets the referenced @p key of the identity constraint. + * + * The key points to a identity constraint of type Key or Unique. + * + * The identity constraint has only a referenced key if its + * type is KeyReference. + * + * @see + */ + void setReferencedKey(const XsdIdentityConstraint::Ptr &key); + + /** + * Returns the referenced key of the identity constraint or an empty + * pointer if its type is not KeyReference. + */ + XsdIdentityConstraint::Ptr referencedKey() const; + + private: + Category m_category; + XsdXPathExpression::Ptr m_selector; + XsdXPathExpression::List m_fields; + XsdIdentityConstraint::Ptr m_referencedKey; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsdinstancereader.cpp b/src/xmlpatterns/schema/qxsdinstancereader.cpp new file mode 100644 index 0000000..81c40c9 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdinstancereader.cpp @@ -0,0 +1,166 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qxsdinstancereader_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +XsdInstanceReader::XsdInstanceReader(const QAbstractXmlNodeModel *model, const XsdSchemaContext::Ptr &context) + : m_context(context) + , m_model(model->iterate(model->root(QXmlNodeModelIndex()), QXmlNodeModelIndex::AxisChild)) +{ +} + +bool XsdInstanceReader::atEnd() const +{ + return (m_model.current() == AbstractXmlPullProvider::EndOfInput); +} + +void XsdInstanceReader::readNext() +{ + m_model.next(); + + if (m_model.current() == AbstractXmlPullProvider::StartElement) { + m_cachedAttributes = m_model.attributes(); + m_cachedAttributeItems = m_model.attributeItems(); + m_cachedSourceLocation = m_model.sourceLocation(); + m_cachedItem = QXmlItem(m_model.index()); + } +} + +bool XsdInstanceReader::isStartElement() const +{ + return (m_model.current() == AbstractXmlPullProvider::StartElement); +} + +bool XsdInstanceReader::isEndElement() const +{ + return (m_model.current() == AbstractXmlPullProvider::EndElement); +} + +bool XsdInstanceReader::hasChildText() const +{ + const QXmlNodeModelIndex index = m_model.index(); + QXmlNodeModelIndex::Iterator::Ptr it = index.model()->iterate(index, QXmlNodeModelIndex::AxisChild); + + QXmlNodeModelIndex currentIndex = it->next(); + while (!currentIndex.isNull()) { + if (currentIndex.kind() == QXmlNodeModelIndex::Text) + return true; + + currentIndex = it->next(); + } + + return false; +} + +bool XsdInstanceReader::hasChildElement() const +{ + const QXmlNodeModelIndex index = m_model.index(); + QXmlNodeModelIndex::Iterator::Ptr it = index.model()->iterate(index, QXmlNodeModelIndex::AxisChild); + + QXmlNodeModelIndex currentIndex = it->next(); + while (!currentIndex.isNull()) { + if (currentIndex.kind() == QXmlNodeModelIndex::Element) + return true; + + currentIndex = it->next(); + } + + return false; +} + +QXmlName XsdInstanceReader::name() const +{ + return m_model.name(); +} + +QXmlName XsdInstanceReader::convertToQName(const QString &name) const +{ + const int pos = name.indexOf(QLatin1Char(':')); + + QXmlName::PrefixCode prefixCode = 0; + QXmlName::NamespaceCode namespaceCode; + QXmlName::LocalNameCode localNameCode; + if (pos != -1) { + prefixCode = m_context->namePool()->allocatePrefix(name.left(pos)); + namespaceCode = m_cachedItem.toNodeModelIndex().namespaceForPrefix(prefixCode); + localNameCode = m_context->namePool()->allocateLocalName(name.mid(pos + 1)); + } else { + prefixCode = StandardPrefixes::empty; + namespaceCode = m_cachedItem.toNodeModelIndex().namespaceForPrefix(prefixCode); + if (namespaceCode == -1) + namespaceCode = StandardNamespaces::empty; + localNameCode = m_context->namePool()->allocateLocalName(name); + } + + return QXmlName(namespaceCode, localNameCode, prefixCode); +} + +bool XsdInstanceReader::hasAttribute(const QXmlName &name) const +{ + return m_cachedAttributes.contains(name); +} + +QString XsdInstanceReader::attribute(const QXmlName &name) const +{ + Q_ASSERT(m_cachedAttributes.contains(name)); + + return m_cachedAttributes.value(name); +} + +QSet XsdInstanceReader::attributeNames() const +{ + return m_cachedAttributes.keys().toSet(); +} + +QString XsdInstanceReader::text() const +{ + const QXmlNodeModelIndex index = m_model.index(); + QXmlNodeModelIndex::Iterator::Ptr it = index.model()->iterate(index, QXmlNodeModelIndex::AxisChild); + + QString result; + + QXmlNodeModelIndex currentIndex = it->next(); + while (!currentIndex.isNull()) { + if (currentIndex.kind() == QXmlNodeModelIndex::Text) { + result.append(Item(currentIndex).stringValue()); + } + + currentIndex = it->next(); + } + + return result; +} + +QXmlItem XsdInstanceReader::item() const +{ + return m_cachedItem; +} + +QXmlItem XsdInstanceReader::attributeItem(const QXmlName &name) const +{ + return m_cachedAttributeItems.value(name); +} + +QSourceLocation XsdInstanceReader::sourceLocation() const +{ + return m_cachedSourceLocation; +} + +QVector XsdInstanceReader::namespaceBindings(const QXmlNodeModelIndex &index) const +{ + return index.namespaceBindings(); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdinstancereader_p.h b/src/xmlpatterns/schema/qxsdinstancereader_p.h new file mode 100644 index 0000000..9df02d6 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdinstancereader_p.h @@ -0,0 +1,159 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdInstanceReader_H +#define Patternist_XsdInstanceReader_H + +#include "qabstractxmlnodemodel.h" +#include "qpullbridge_p.h" +#include "qxsdschemacontext_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short The schema instance reader. + * + * This class reads in a xml instance document from a QAbstractXmlNodeModel + * and provides a QXmlStreamReader like interface with some additional context + * information. + * + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdInstanceReader + { + public: + typedef QExplicitlySharedDataPointer Ptr; + + /** + * Creates a new instance reader that will read the data from + * the given @p model. + * + * @param model The model the data are read from. + * @param context The context that is used for error reporting etc. + */ + XsdInstanceReader(const QAbstractXmlNodeModel *model, const XsdSchemaContext::Ptr &context); + + protected: + /** + * Returns @c true if the end of the document is reached, @c false otherwise. + */ + bool atEnd() const; + + /** + * Reads the next node from the document. + */ + void readNext(); + + /** + * Returns whether the current node is a start element. + */ + bool isStartElement() const; + + /** + * Returns whether the current node is an end element. + */ + bool isEndElement() const; + + /** + * Returns whether the current node has a text node among its children. + */ + bool hasChildText() const; + + /** + * Returns whether the current node has an element node among its children. + */ + bool hasChildElement() const; + + /** + * Returns the name of the current node. + */ + QXmlName name() const; + + /** + * Returns whether the current node has an attribute with the given @p name. + */ + bool hasAttribute(const QXmlName &name) const; + + /** + * Returns the attribute with the given @p name of the current node. + */ + QString attribute(const QXmlName &name) const; + + /** + * Returns the list of attribute names of the current node. + */ + QSet attributeNames() const; + + /** + * Returns the concatenated text of all direct child text nodes. + */ + QString text() const; + + /** + * Converts a qualified name into a QXmlName according to the namespace + * mappings of the current node. + */ + QXmlName convertToQName(const QString &name) const; + + /** + * Returns a source location object for the current position. + */ + QSourceLocation sourceLocation() const; + + /** + * Returns the QXmlItem for the current position. + */ + QXmlItem item() const; + + /** + * Returns the QXmlItem for the attribute with the given @p name at the current position. + */ + QXmlItem attributeItem(const QXmlName &name) const; + + /** + * Returns the namespace bindings for the given node model @p index. + */ + QVector namespaceBindings(const QXmlNodeModelIndex &index) const; + + /** + * The shared schema context. + */ + XsdSchemaContext::Ptr m_context; + + private: + PullBridge m_model; + QHash m_cachedAttributes; + QHash m_cachedAttributeItems; + QSourceLocation m_cachedSourceLocation; + QXmlItem m_cachedItem; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsdmodelgroup.cpp b/src/xmlpatterns/schema/qxsdmodelgroup.cpp new file mode 100644 index 0000000..1245822 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdmodelgroup.cpp @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qxsdmodelgroup_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +XsdModelGroup::XsdModelGroup() + : m_compositor(SequenceCompositor) +{ +} + +bool XsdModelGroup::isModelGroup() const +{ + return true; +} + +void XsdModelGroup::setCompositor(ModelCompositor compositor) +{ + m_compositor = compositor; +} + +XsdModelGroup::ModelCompositor XsdModelGroup::compositor() const +{ + return m_compositor; +} + +void XsdModelGroup::setParticles(const XsdParticle::List &particles) +{ + m_particles = particles; +} + +XsdParticle::List XsdModelGroup::particles() const +{ + return m_particles; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdmodelgroup_p.h b/src/xmlpatterns/schema/qxsdmodelgroup_p.h new file mode 100644 index 0000000..b7b59ac --- /dev/null +++ b/src/xmlpatterns/schema/qxsdmodelgroup_p.h @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdModelGroup_H +#define Patternist_XsdModelGroup_H + +#include "qxsdparticle_p.h" +#include "qxsdterm_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +template class QList; + +namespace QPatternist +{ + /** + * @short Represents a XSD model group object. + * + * This class represents the model group object of a XML schema as described + * here. + * + * It contains information from either a sequence object, a choice object or an + * all object. + * + * @see XML Schema API reference + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdModelGroup : public XsdTerm + { + public: + typedef QExplicitlySharedDataPointer Ptr; + typedef QList List; + + /** + * Describes the compositor of the model group. + */ + enum ModelCompositor + { + SequenceCompositor, ///< The model group is a sequence. + ChoiceCompositor, ///< The model group is a choice. + AllCompositor ///< The model group contains elements only. + }; + + /** + * Creates a new model group object. + */ + XsdModelGroup(); + + /** + * Returns always @c true, used to avoid dynamic casts. + */ + virtual bool isModelGroup() const; + + /** + * Sets the @p compositor of the model group. + * + * @see ModelCompositor + */ + void setCompositor(ModelCompositor compositor); + + /** + * Returns the compositor of the model group. + */ + ModelCompositor compositor() const; + + /** + * Sets the list of @p particles of the model group. + * + * @see Particles Definition + */ + void setParticles(const XsdParticle::List &particles); + + /** + * Returns the list of particles of the model group. + */ + XsdParticle::List particles() const; + + private: + ModelCompositor m_compositor; + XsdParticle::List m_particles; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsdnotation.cpp b/src/xmlpatterns/schema/qxsdnotation.cpp new file mode 100644 index 0000000..cfa0cd3 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdnotation.cpp @@ -0,0 +1,38 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qxsdnotation_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +void XsdNotation::setPublicId(const DerivedString::Ptr &id) +{ + m_publicId = id; +} + +DerivedString::Ptr XsdNotation::publicId() const +{ + return m_publicId; +} + +void XsdNotation::setSystemId(const AnyURI::Ptr &id) +{ + m_systemId = id; +} + +AnyURI::Ptr XsdNotation::systemId() const +{ + return m_systemId; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdnotation_p.h b/src/xmlpatterns/schema/qxsdnotation_p.h new file mode 100644 index 0000000..dc1d597 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdnotation_p.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdNotation_H +#define Patternist_XsdNotation_H + +#include "qanyuri_p.h" +#include "qderivedstring_p.h" +#include "qnamedschemacomponent_p.h" +#include "qxsdannotated_p.h" + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Represents a XSD notation object, which should not + * be confused with the atomic type @c xs:NOTATION. + * + * This class represents the notation object of a XML schema as described + * here. + * + * @see XML Schema API reference + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdNotation : public NamedSchemaComponent, public XsdAnnotated + { + public: + typedef QExplicitlySharedDataPointer Ptr; + typedef QList List; + + /** + * Sets the public @p identifier of the notation. + * + * @see Public Identifier Definition + */ + void setPublicId(const DerivedString::Ptr &identifier); + + /** + * Returns the public identifier of the notation. + */ + DerivedString::Ptr publicId() const; + + /** + * Sets the system @p identifier of the notation. + * + * @see System Identifier Definition + */ + void setSystemId(const AnyURI::Ptr &identifier); + + /** + * Returns the system identifier of the notation. + */ + AnyURI::Ptr systemId() const; + + private: + DerivedString::Ptr m_publicId; + AnyURI::Ptr m_systemId; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsdparticle.cpp b/src/xmlpatterns/schema/qxsdparticle.cpp new file mode 100644 index 0000000..a2671fa --- /dev/null +++ b/src/xmlpatterns/schema/qxsdparticle.cpp @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qxsdparticle_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +XsdParticle::XsdParticle() + : m_minimumOccurs(1) + , m_maximumOccurs(1) + , m_maximumOccursUnbounded(false) +{ +} + +void XsdParticle::setMinimumOccurs(unsigned int occurs) +{ + m_minimumOccurs = occurs; +} + +unsigned int XsdParticle::minimumOccurs() const +{ + return m_minimumOccurs; +} + +void XsdParticle::setMaximumOccurs(unsigned int occurs) +{ + m_maximumOccurs = occurs; +} + +unsigned int XsdParticle::maximumOccurs() const +{ + return m_maximumOccurs; +} + +void XsdParticle::setMaximumOccursUnbounded(bool unbounded) +{ + m_maximumOccursUnbounded = unbounded; +} + +bool XsdParticle::maximumOccursUnbounded() const +{ + return m_maximumOccursUnbounded; +} + +void XsdParticle::setTerm(const XsdTerm::Ptr &term) +{ + m_term = term; +} + +XsdTerm::Ptr XsdParticle::term() const +{ + return m_term; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdparticle_p.h b/src/xmlpatterns/schema/qxsdparticle_p.h new file mode 100644 index 0000000..61e3eb3 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdparticle_p.h @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdParticle_H +#define Patternist_XsdParticle_H + +#include "qnamedschemacomponent_p.h" +#include "qxsdterm_p.h" + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Represents a XSD particle object. + * + * This class represents the particle object of a XML schema as described + * here. + * + * It contains information about the number of occurrence and a reference to + * either an element object, a group object or an any object. + * + * @see XML Schema API reference + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdParticle : public NamedSchemaComponent + { + public: + typedef QExplicitlySharedDataPointer Ptr; + typedef QList List; + + /** + * Creates a new particle object. + */ + XsdParticle(); + + /** + * Sets the minimum @p occurrence of the particle. + * + * @see Minimum Occurrence Definition + */ + void setMinimumOccurs(unsigned int occurrence); + + /** + * Returns the minimum occurrence of the particle. + */ + unsigned int minimumOccurs() const; + + /** + * Sets the maximum @p occurrence of the particle. + * + * @see Maximum Occurrence Definition + */ + void setMaximumOccurs(unsigned int occurrence); + + /** + * Returns the maximum occurrence of the particle. + * + * @note This value has only a meaning if maximumOccursUnbounded is @c false. + */ + unsigned int maximumOccurs() const; + + /** + * Sets whether the maximum occurrence of the particle is unbounded. + * + * @see Maximum Occurrence Definition + */ + void setMaximumOccursUnbounded(bool unbounded); + + /** + * Returns whether the maximum occurrence of the particle is unbounded. + */ + bool maximumOccursUnbounded() const; + + /** + * Sets the @p term of the particle. + * + * The term can be an element, a model group or an element wildcard. + * + * @see Term Definition + */ + void setTerm(const XsdTerm::Ptr &term); + + /** + * Returns the term of the particle. + */ + XsdTerm::Ptr term() const; + + private: + unsigned int m_minimumOccurs; + unsigned int m_maximumOccurs; + bool m_maximumOccursUnbounded; + XsdTerm::Ptr m_term; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsdparticlechecker.cpp b/src/xmlpatterns/schema/qxsdparticlechecker.cpp new file mode 100644 index 0000000..1bdef00 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdparticlechecker.cpp @@ -0,0 +1,510 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qxsdparticlechecker_p.h" + +#include "qxsdelement_p.h" +#include "qxsdmodelgroup_p.h" +#include "qxsdschemahelper_p.h" +#include "qxsdstatemachine_p.h" +#include "qxsdstatemachinebuilder_p.h" +#include "qxsdtypechecker_p.h" + +#include + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +namespace QPatternist +{ + /** + * This template specialization is picked up by XsdStateMachine and allows us + * to print nice edge labels. + */ + template <> + QString XsdStateMachine::transitionTypeToString(XsdTerm::Ptr term) const + { + if (!term) + return QLatin1String("(empty)"); + + if (term->isElement()) { + return XsdElement::Ptr(term)->displayName(m_namePool); + } else if (term->isWildcard()) { + const XsdWildcard::Ptr wildcard(term); + return QLatin1String("(wildcard)"); + } else { + return QString(); + } + } +} + +/** + * This method is used by the isUPAConform method to check whether @p term and @p otherTerm + * are the same resp. match each other. + */ +static bool termMatches(const XsdTerm::Ptr &term, const XsdTerm::Ptr &otherTerm, const NamePool::Ptr &namePool) +{ + if (term->isElement()) { + const XsdElement::Ptr element(term); + + if (otherTerm->isElement()) { + // both, the term and the other term are elements + + const XsdElement::Ptr otherElement(otherTerm); + + // if they have the same name they match + if (element->name(namePool) == otherElement->name(namePool)) + return true; + + } else if (otherTerm->isWildcard()) { + // the term is an element and the other term a wildcard + + const XsdWildcard::Ptr wildcard(otherTerm); + + // wildcards using XsdWildcard::absentNamespace, so we have to fix that here + QXmlName name = element->name(namePool); + if (name.namespaceURI() == StandardNamespaces::empty) + name.setNamespaceURI(namePool->allocateNamespace(XsdWildcard::absentNamespace())); + + // if the wildcards namespace constraint allows the elements name, they match + if (XsdSchemaHelper::wildcardAllowsExpandedName(name, wildcard, namePool)) + return true; + } + } else if (term->isWildcard()) { + const XsdWildcard::Ptr wildcard(term); + + if (otherTerm->isElement()) { + // the term is a wildcard and the other term an element + + const XsdElement::Ptr otherElement(otherTerm); + + // wildcards using XsdWildcard::absentNamespace, so we have to fix that here + QXmlName name = otherElement->name(namePool); + if (name.namespaceURI() == StandardNamespaces::empty) + name.setNamespaceURI(namePool->allocateNamespace(XsdWildcard::absentNamespace())); + + // if the wildcards namespace constraint allows the elements name, they match + if (XsdSchemaHelper::wildcardAllowsExpandedName(name, wildcard, namePool)) + return true; + + } else if (otherTerm->isWildcard()) { + // both, the term and the other term are wildcards + + const XsdWildcard::Ptr otherWildcard(otherTerm); + + // check if the range of the wildcard overlaps. + const XsdWildcard::Ptr intersectionWildcard = XsdSchemaHelper::wildcardIntersection(wildcard, otherWildcard); + if (!intersectionWildcard || + (intersectionWildcard && !(intersectionWildcard->namespaceConstraint()->variety() != XsdWildcard::NamespaceConstraint::Not && intersectionWildcard->namespaceConstraint()->namespaces().isEmpty()))) + return true; + } + } + + return false; +} + +/** + * This method is used by the subsumes algorithm to check whether the @p derivedTerm is validly derived from the @p baseTerm. + * + * @param baseTerm The term of the base component (type or group). + * @param derivedTerm The term of the derived component (type or group). + * @param particles A hash to map the passed base and derived term to the particles they belong to. + * @param context The schema context. + * @param errorMsg The error message in the case that an error occurs. + */ +static bool derivedTermValid(const XsdTerm::Ptr &baseTerm, const XsdTerm::Ptr &derivedTerm, const QHash &particles, const XsdSchemaContext::Ptr &context, QString &errorMsg) +{ + const NamePool::Ptr namePool(context->namePool()); + + // find the particles where the base and derived term belongs to + const XsdParticle::Ptr baseParticle = particles.value(baseTerm); + const XsdParticle::Ptr derivedParticle = particles.value(derivedTerm); + + // check that an empty particle can not be derived from a non-empty particle + if (derivedParticle && baseParticle) { + if (XsdSchemaHelper::isParticleEmptiable(derivedParticle) && !XsdSchemaHelper::isParticleEmptiable(baseParticle)) { + errorMsg = QtXmlPatterns::tr("empty particle cannot be derived from non-empty particle"); + return false; + } + } + + if (baseTerm->isElement()) { + const XsdElement::Ptr element(baseTerm); + + if (derivedTerm->isElement()) { + // if both terms are elements + + const XsdElement::Ptr derivedElement(derivedTerm); + + // check names are equal + if (element->name(namePool) != derivedElement->name(namePool)) { + errorMsg = QtXmlPatterns::tr("derived particle is missing element %1").arg(formatKeyword(element->displayName(namePool))); + return false; + } + + // check value constraints are equal (if available) + if (element->valueConstraint() && element->valueConstraint()->variety() == XsdElement::ValueConstraint::Fixed) { + if (!derivedElement->valueConstraint()) { + errorMsg = QtXmlPatterns::tr("derived element %1 is missing value constraint as defined in base particle").arg(formatKeyword(derivedElement->displayName(namePool))); + return false; + } + + if (derivedElement->valueConstraint()->variety() != XsdElement::ValueConstraint::Fixed) { + errorMsg = QtXmlPatterns::tr("derived element %1 has weaker value constraint than base particle").arg(formatKeyword(derivedElement->displayName(namePool))); + return false; + } + + const QSourceLocation dummyLocation(QUrl(QLatin1String("http://dummy.org")), 1, 1); + const XsdTypeChecker checker(context, QVector(), dummyLocation); + if (!checker.valuesAreEqual(element->valueConstraint()->value(), derivedElement->valueConstraint()->value(), derivedElement->type())) { + errorMsg = QtXmlPatterns::tr("fixed value constraint of element %1 differs from value constraint in base particle").arg(formatKeyword(derivedElement->displayName(namePool))); + return false; + } + } + + // check that a derived element can not be nillable if the base element is not nillable + if (!element->isNillable() && derivedElement->isNillable()) { + errorMsg = QtXmlPatterns::tr("derived element %1 cannot be nillable as base element is not nillable").arg(formatKeyword(derivedElement->displayName(namePool))); + return false; + } + + // check that the constraints of the derived element are more strict then the constraints of the base element + const XsdElement::BlockingConstraints baseConstraints = element->disallowedSubstitutions(); + const XsdElement::BlockingConstraints derivedConstraints = derivedElement->disallowedSubstitutions(); + if ((baseConstraints & XsdElement::RestrictionConstraint) && !(derivedConstraints & XsdElement::RestrictionConstraint) || + (baseConstraints & XsdElement::ExtensionConstraint) && !(derivedConstraints & XsdElement::ExtensionConstraint) || + (baseConstraints & XsdElement::SubstitutionConstraint) && !(derivedConstraints & XsdElement::SubstitutionConstraint)) { + errorMsg = QtXmlPatterns::tr("block constraints of derived element %1 must not be more weaker than in the base element").arg(formatKeyword(derivedElement->displayName(namePool))); + return false; + } + + // if the type of both elements is the same we can stop testing here + if (element->type()->name(namePool) == derivedElement->type()->name(namePool)) + return true; + + // check that the type of the derived element can validly derived from the type of the base element + if (derivedElement->type()->isSimpleType()) { + if (!XsdSchemaHelper::isSimpleDerivationOk(derivedElement->type(), element->type(), SchemaType::DerivationConstraints())) { + errorMsg = QtXmlPatterns::tr("simple type of derived element %1 cannot be validly derived from base element").arg(formatKeyword(derivedElement->displayName(namePool))); + return false; + } + } else if (derivedElement->type()->isComplexType()) { + if (!XsdSchemaHelper::isComplexDerivationOk(derivedElement->type(), element->type(), SchemaType::DerivationConstraints())) { + errorMsg = QtXmlPatterns::tr("complex type of derived element %1 cannot be validly derived from base element").arg(formatKeyword(derivedElement->displayName(namePool))); + return false; + } + } + + // if both, derived and base element, have a complex type that contains a particle itself, apply the subsumes algorithm + // recursive on their particles + if (element->type()->isComplexType() && derivedElement->type()->isComplexType()) { + if (element->type()->isDefinedBySchema() && derivedElement->type()->isDefinedBySchema()) { + const XsdComplexType::Ptr baseType(element->type()); + const XsdComplexType::Ptr derivedType(derivedElement->type()); + if ((baseType->contentType()->variety() == XsdComplexType::ContentType::ElementOnly || + baseType->contentType()->variety() == XsdComplexType::ContentType::Mixed) && + (derivedType->contentType()->variety() == XsdComplexType::ContentType::ElementOnly || + derivedType->contentType()->variety() == XsdComplexType::ContentType::Mixed)) { + + return XsdParticleChecker::subsumes(baseType->contentType()->particle(), derivedType->contentType()->particle(), context, errorMsg); + } + } + } + + return true; + } else if (derivedTerm->isWildcard()) { + // derive a wildcard from an element is not allowed + errorMsg = QtXmlPatterns::tr("element %1 is missing in derived particle").arg(formatKeyword(element->displayName(namePool))); + return false; + } + } else if (baseTerm->isWildcard()) { + const XsdWildcard::Ptr wildcard(baseTerm); + + if (derivedTerm->isElement()) { + // the base term is a wildcard and derived term an element + + const XsdElement::Ptr derivedElement(derivedTerm); + + // wildcards using XsdWildcard::absentNamespace, so we have to fix that here + QXmlName name = derivedElement->name(namePool); + if (name.namespaceURI() == StandardNamespaces::empty) + name.setNamespaceURI(namePool->allocateNamespace(XsdWildcard::absentNamespace())); + + // check that name of the element is allowed by the wildcards namespace constraint + if (!XsdSchemaHelper::wildcardAllowsExpandedName(name, wildcard, namePool)) { + errorMsg = QtXmlPatterns::tr("element %1 does not match namespace constraint of wildcard in base particle").arg(formatKeyword(derivedElement->displayName(namePool))); + return false; + } + + } else if (derivedTerm->isWildcard()) { + // both, derived and base term are wildcards + + const XsdWildcard::Ptr derivedWildcard(derivedTerm); + + // check that the derived wildcard is a valid subset of the base wildcard + if (!XsdSchemaHelper::isWildcardSubset(derivedWildcard, wildcard)) { + errorMsg = QtXmlPatterns::tr("wildcard in derived particle is not a valid subset of wildcard in base particle"); + return false; + } + + if (!XsdSchemaHelper::checkWildcardProcessContents(wildcard, derivedWildcard)) { + errorMsg = QtXmlPatterns::tr("processContent of wildcard in derived particle is weaker than wildcard in base particle"); + return false; + } + } + + return true; + } + + return false; +} + +typedef QHash ElementHash; + +/** + * Internal helper method that checks if the given @p particle contains an element with the + * same name and type twice. + */ +static bool hasDuplicatedElementsInternal(const XsdParticle::Ptr &particle, const NamePool::Ptr &namePool, ElementHash &hash, XsdElement::Ptr &conflictingElement) +{ + const XsdTerm::Ptr term = particle->term(); + if (term->isElement()) { + const XsdElement::Ptr mainElement(term); + XsdElement::List substGroups = mainElement->substitutionGroups(); + if (substGroups.isEmpty()) + substGroups << mainElement; + + for (int i = 0; i < substGroups.count(); ++i) { + const XsdElement::Ptr element = substGroups.at(i); + if (hash.contains(element->name(namePool))) { + if (element->type()->name(namePool) != hash.value(element->name(namePool))->type()->name(namePool)) { + conflictingElement = element; + return true; + } + } else { + hash.insert(element->name(namePool), element); + } + } + } else if (term->isModelGroup()) { + const XsdModelGroup::Ptr group(term); + const XsdParticle::List particles = group->particles(); + for (int i = 0; i < particles.count(); ++i) { + if (hasDuplicatedElementsInternal(particles.at(i), namePool, hash, conflictingElement)) + return true; + } + } + + return false; +} + +bool XsdParticleChecker::hasDuplicatedElements(const XsdParticle::Ptr &particle, const NamePool::Ptr &namePool, XsdElement::Ptr &conflictingElement) +{ + ElementHash hash; + return hasDuplicatedElementsInternal(particle, namePool, hash, conflictingElement); +} + +bool XsdParticleChecker::isUPAConform(const XsdParticle::Ptr &particle, const NamePool::Ptr &namePool) +{ + /** + * The algorithm is implemented like described in http://www.ltg.ed.ac.uk/~ht/XML_Europe_2003.html#S2.2 + */ + + // create a state machine for the given particle + XsdStateMachine stateMachine(namePool); + + XsdStateMachineBuilder builder(&stateMachine, namePool); + const XsdStateMachine::StateId endState = builder.reset(); + const XsdStateMachine::StateId startState = builder.buildParticle(particle, endState); + builder.addStartState(startState); + +/* + static int counter = 0; + { + QFile file(QString("/tmp/file_upa%1.dot").arg(counter)); + file.open(QIODevice::WriteOnly); + stateMachine.outputGraph(&file, "Base"); + file.close(); + } + ::system(QString("dot -Tpng /tmp/file_upa%1.dot -o/tmp/file_upa%1.png").arg(counter).toLatin1().data()); +*/ + const XsdStateMachine dfa = stateMachine.toDFA(); +/* + { + QFile file(QString("/tmp/file_upa%1dfa.dot").arg(counter)); + file.open(QIODevice::WriteOnly); + dfa.outputGraph(&file, "Base"); + file.close(); + } + ::system(QString("dot -Tpng /tmp/file_upa%1dfa.dot -o/tmp/file_upa%1dfa.png").arg(counter).toLatin1().data()); +*/ + const QHash::StateId, XsdStateMachine::StateType> states = dfa.states(); + const QHash::StateId, QHash::StateId> > > transitions = dfa.transitions(); + + // the basic idea of that algorithm is to iterate over all states of that machine and check that no two edges + // that match on the same term leave a state, so for a given term it should always be obvious which edge to take + QHashIterator::StateId, XsdStateMachine::StateType> stateIt(states); + while (stateIt.hasNext()) { // iterate over all states + stateIt.next(); + + // fetch all transitions the current state allows + const QHash::StateId> > currentTransitions = transitions.value(stateIt.key()); + QHashIterator::StateId> > transitionIt(currentTransitions); + while (transitionIt.hasNext()) { // iterate over all transitions + transitionIt.next(); + + if (transitionIt.value().size() > 1) { + // we have one state with two edges leaving it, that means + // the XsdTerm::Ptr exists twice, that is an error + return false; + } + + QHashIterator::StateId> > innerTransitionIt(currentTransitions); + while (innerTransitionIt.hasNext()) { // iterate over all transitions again, as we have to compare all transitions with all + innerTransitionIt.next(); + + if (transitionIt.key() == innerTransitionIt.key()) // do no compare with ourself + continue; + + // use the helper method termMatches to check if both term matches + if (termMatches(transitionIt.key(), innerTransitionIt.key(), namePool)) + return false; + } + } + } + + return true; +} + +bool XsdParticleChecker::subsumes(const XsdParticle::Ptr &particle, const XsdParticle::Ptr &derivedParticle, const XsdSchemaContext::Ptr &context, QString &errorMsg) +{ + /** + * The algorithm is implemented like described in http://www.ltg.ed.ac.uk/~ht/XML_Europe_2003.html#S2.3 + */ + + const NamePool::Ptr namePool(context->namePool()); + + XsdStateMachine baseStateMachine(namePool); + XsdStateMachine derivedStateMachine(namePool); + + // build up state machines for both particles + { + XsdStateMachineBuilder builder(&baseStateMachine, namePool); + const XsdStateMachine::StateId endState = builder.reset(); + const XsdStateMachine::StateId startState = builder.buildParticle(particle, endState); + builder.addStartState(startState); + + baseStateMachine = baseStateMachine.toDFA(); + } + { + XsdStateMachineBuilder builder(&derivedStateMachine, namePool); + const XsdStateMachine::StateId endState = builder.reset(); + const XsdStateMachine::StateId startState = builder.buildParticle(derivedParticle, endState); + builder.addStartState(startState); + + derivedStateMachine = derivedStateMachine.toDFA(); + } + + QHash particlesHash = XsdStateMachineBuilder::particleLookupMap(particle); + particlesHash.unite(XsdStateMachineBuilder::particleLookupMap(derivedParticle)); + +/* + static int counter = 0; + { + QFile file(QString("/tmp/file_base%1.dot").arg(counter)); + file.open(QIODevice::WriteOnly); + baseStateMachine.outputGraph(&file, QLatin1String("Base")); + file.close(); + } + { + QFile file(QString("/tmp/file_derived%1.dot").arg(counter)); + file.open(QIODevice::WriteOnly); + derivedStateMachine.outputGraph(&file, QLatin1String("Base")); + file.close(); + } + ::system(QString("dot -Tpng /tmp/file_base%1.dot -o/tmp/file_base%1.png").arg(counter).toLatin1().data()); + ::system(QString("dot -Tpng /tmp/file_derived%1.dot -o/tmp/file_derived%1.png").arg(counter).toLatin1().data()); +*/ + + const XsdStateMachine::StateId baseStartState = baseStateMachine.startState(); + const QHash::StateId, XsdStateMachine::StateType> baseStates = baseStateMachine.states(); + const QHash::StateId, QHash::StateId> > > baseTransitions = baseStateMachine.transitions(); + + const XsdStateMachine::StateId derivedStartState = derivedStateMachine.startState(); + const QHash::StateId, XsdStateMachine::StateType> derivedStates = derivedStateMachine.states(); + const QHash::StateId, QHash::StateId> > > derivedTransitions = derivedStateMachine.transitions(); + + // @see http://www.ltg.ed.ac.uk/~ht/XML_Europe_2003.html#S2.3.1 + + // define working set + QList::StateId, XsdStateMachine::StateId> > workSet; + QList::StateId, XsdStateMachine::StateId> > processedSet; + + // 1) fill working set initially with start states + workSet.append(qMakePair::StateId, XsdStateMachine::StateId>(baseStartState, derivedStartState)); + processedSet.append(qMakePair::StateId, XsdStateMachine::StateId>(baseStartState, derivedStartState)); + + while (!workSet.isEmpty()) { // while there are state sets to process + + // 3) dequeue on state set + const QPair::StateId, XsdStateMachine::StateId> set = workSet.takeFirst(); + + const QHash::StateId> > derivedTrans = derivedTransitions.value(set.second); + QHashIterator::StateId> > derivedIt(derivedTrans); + + const QHash::StateId> > baseTrans = baseTransitions.value(set.first); + + while (derivedIt.hasNext()) { + derivedIt.next(); + + bool found = false; + QHashIterator::StateId> > baseIt(baseTrans); + while (baseIt.hasNext()) { + baseIt.next(); + if (derivedTermValid(baseIt.key(), derivedIt.key(), particlesHash, context, errorMsg)) { + const QPair::StateId, XsdStateMachine::StateId> endSet = + qMakePair::StateId, XsdStateMachine::StateId>(baseIt.value().first(), derivedIt.value().first()); + if (!processedSet.contains(endSet) && !workSet.contains(endSet)) { + workSet.append(endSet); + processedSet.append(endSet); + } + + found = true; + } + } + + if (!found) { + return false; + } + } + } + + // 5) + QHashIterator::StateId, XsdStateMachine::StateType> it(derivedStates); + while (it.hasNext()) { + it.next(); + + if (it.value() == XsdStateMachine::EndState || it.value() == XsdStateMachine::StartEndState) { + for (int i = 0; i < processedSet.count(); ++i) { + if (processedSet.at(i).second == it.key() && + (baseStates.value(processedSet.at(i).first) != XsdStateMachine::EndState && + baseStates.value(processedSet.at(i).first) != XsdStateMachine::StartEndState)) { + errorMsg = QtXmlPatterns::tr("derived particle allows content that is not allowed in the base particle"); + return false; + } + } + } + } + + return true; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdparticlechecker_p.h b/src/xmlpatterns/schema/qxsdparticlechecker_p.h new file mode 100644 index 0000000..16a8d95 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdparticlechecker_p.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdParticleChecker_H +#define Patternist_XsdParticleChecker_H + +#include "qxsdelement_p.h" +#include "qxsdparticle_p.h" +#include "qxsdschemacontext_p.h" +#include "qxsdwildcard_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short A helper class to check validity of particles. + * + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdParticleChecker + { + public: + /** + * Checks whether the given @p particle has two or more element + * declarations with the same name but different type definitions. + */ + static bool hasDuplicatedElements(const XsdParticle::Ptr &particle, const NamePool::Ptr &namePool, XsdElement::Ptr &conflictingElement); + + /** + * Checks whether the given @p particle is valid according the + * UPA (http://www.w3.org/TR/xmlschema-1/#cos-nonambig) constraint. + */ + static bool isUPAConform(const XsdParticle::Ptr &particle, const NamePool::Ptr &namePool); + + /** + * Checks whether the given @p particle subsumes the given @p derivedParticle. + * (http://www.w3.org/TR/xmlschema-1/#cos-particle-restrict) + */ + static bool subsumes(const XsdParticle::Ptr &particle, const XsdParticle::Ptr &derivedParticle, const XsdSchemaContext::Ptr &context, QString &errorMsg); + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsdreference.cpp b/src/xmlpatterns/schema/qxsdreference.cpp new file mode 100644 index 0000000..0a934dd --- /dev/null +++ b/src/xmlpatterns/schema/qxsdreference.cpp @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qxsdreference_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +bool XsdReference::isReference() const +{ + return true; +} + +void XsdReference::setType(Type type) +{ + m_type = type; +} + +XsdReference::Type XsdReference::type() const +{ + return m_type; +} + +void XsdReference::setReferenceName(const QXmlName &referenceName) +{ + m_referenceName = referenceName; +} + +QXmlName XsdReference::referenceName() const +{ + return m_referenceName; +} + +void XsdReference::setSourceLocation(const QSourceLocation &location) +{ + m_sourceLocation = location; +} + +QSourceLocation XsdReference::sourceLocation() const +{ + return m_sourceLocation; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdreference_p.h b/src/xmlpatterns/schema/qxsdreference_p.h new file mode 100644 index 0000000..afcca25 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdreference_p.h @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdReference_H +#define Patternist_XsdReference_H + +#include "qxsdterm_p.h" + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short A helper class for element and group reference resolving. + * + * For easy resolving of element and group references, we have this class + * that can be used as a place holder for the real element or group + * object it is referring to. + * So whenever the parser detects an element or group reference, it creates + * a XsdReference and returns it instead of the XsdElement or XsdModelGroup. + * During a later phase, the resolver will look for all XsdReferences + * in the schema and will replace them with their referring XsdElement or + * XsdModelGroup objects. + * + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdReference : public XsdTerm + { + public: + typedef QExplicitlySharedDataPointer Ptr; + + /** + * Describes the type of the reference. + */ + enum Type + { + Element, ///< The reference points to an element. + ModelGroup ///< The reference points to a model group. + }; + + /** + * Returns always @c true, used to avoid dynamic casts. + */ + virtual bool isReference() const; + + /** + * Sets the @p type of the reference. + * + * @see Type + */ + void setType(Type type); + + /** + * Returns the type of the reference. + */ + Type type() const; + + /** + * Sets the @p name of the referenced object. + * + * The name can either be a top-level element declaration + * or a top-level group declaration. + */ + void setReferenceName(const QXmlName &ame); + + /** + * Returns the name of the referenced object. + */ + QXmlName referenceName() const; + + /** + * Sets the source @p location where the reference is located. + */ + void setSourceLocation(const QSourceLocation &location); + + /** + * Returns the source location where the reference is located. + */ + QSourceLocation sourceLocation() const; + + private: + Type m_type; + QXmlName m_referenceName; + QSourceLocation m_sourceLocation; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsdschema.cpp b/src/xmlpatterns/schema/qxsdschema.cpp new file mode 100644 index 0000000..260b06b --- /dev/null +++ b/src/xmlpatterns/schema/qxsdschema.cpp @@ -0,0 +1,242 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qxsdschema_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +XsdSchema::XsdSchema(const NamePool::Ptr &namePool) + : m_namePool(namePool) +{ +} + +XsdSchema::~XsdSchema() +{ +} + +NamePool::Ptr XsdSchema::namePool() const +{ + return m_namePool; +} + +void XsdSchema::setTargetNamespace(const QString &targetNamespace) +{ + m_targetNamespace = targetNamespace; +} + +QString XsdSchema::targetNamespace() const +{ + return m_targetNamespace; +} + +void XsdSchema::addElement(const XsdElement::Ptr &element) +{ + const QWriteLocker locker(&m_lock); + + m_elements.insert(element->name(m_namePool), element); +} + +XsdElement::Ptr XsdSchema::element(const QXmlName &name) const +{ + const QReadLocker locker(&m_lock); + + return m_elements.value(name); +} + +XsdElement::List XsdSchema::elements() const +{ + const QReadLocker locker(&m_lock); + + return m_elements.values(); +} + +void XsdSchema::addAttribute(const XsdAttribute::Ptr &attribute) +{ + const QWriteLocker locker(&m_lock); + + m_attributes.insert(attribute->name(m_namePool), attribute); +} + +XsdAttribute::Ptr XsdSchema::attribute(const QXmlName &name) const +{ + const QReadLocker locker(&m_lock); + + return m_attributes.value(name); +} + +XsdAttribute::List XsdSchema::attributes() const +{ + const QReadLocker locker(&m_lock); + + return m_attributes.values(); +} + +void XsdSchema::addType(const SchemaType::Ptr &type) +{ + const QWriteLocker locker(&m_lock); + + m_types.insert(type->name(m_namePool), type); +} + +SchemaType::Ptr XsdSchema::type(const QXmlName &name) const +{ + const QReadLocker locker(&m_lock); + + return m_types.value(name); +} + +SchemaType::List XsdSchema::types() const +{ + const QReadLocker locker(&m_lock); + + return m_types.values(); +} + +XsdSimpleType::List XsdSchema::simpleTypes() const +{ + QReadLocker locker(&m_lock); + + XsdSimpleType::List retval; + + const SchemaType::List types = m_types.values(); + for (int i = 0; i < types.count(); ++i) { + if (types.at(i)->isSimpleType() && types.at(i)->isDefinedBySchema()) + retval.append(types.at(i)); + } + + return retval; +} + +XsdComplexType::List XsdSchema::complexTypes() const +{ + QReadLocker locker(&m_lock); + + XsdComplexType::List retval; + + const SchemaType::List types = m_types.values(); + for (int i = 0; i < types.count(); ++i) { + if (types.at(i)->isComplexType() && types.at(i)->isDefinedBySchema()) + retval.append(types.at(i)); + } + + return retval; +} + +void XsdSchema::addAnonymousType(const SchemaType::Ptr &type) +{ + const QWriteLocker locker(&m_lock); + + // search for not used anonymous type name + QXmlName typeName = type->name(m_namePool); + while (m_anonymousTypes.contains(typeName)) { + typeName = m_namePool->allocateQName(QString(), QLatin1String("merged_") + m_namePool->stringForLocalName(typeName.localName()), QString()); + } + + m_anonymousTypes.insert(typeName, type); +} + +SchemaType::List XsdSchema::anonymousTypes() const +{ + const QReadLocker locker(&m_lock); + + return m_anonymousTypes.values(); +} + +void XsdSchema::addAttributeGroup(const XsdAttributeGroup::Ptr &group) +{ + const QWriteLocker locker(&m_lock); + + m_attributeGroups.insert(group->name(m_namePool), group); +} + +XsdAttributeGroup::Ptr XsdSchema::attributeGroup(const QXmlName name) const +{ + const QReadLocker locker(&m_lock); + + return m_attributeGroups.value(name); +} + +XsdAttributeGroup::List XsdSchema::attributeGroups() const +{ + const QReadLocker locker(&m_lock); + + return m_attributeGroups.values(); +} + +void XsdSchema::addElementGroup(const XsdModelGroup::Ptr &group) +{ + const QWriteLocker locker(&m_lock); + + m_elementGroups.insert(group->name(m_namePool), group); +} + +XsdModelGroup::Ptr XsdSchema::elementGroup(const QXmlName &name) const +{ + const QReadLocker locker(&m_lock); + + return m_elementGroups.value(name); +} + +XsdModelGroup::List XsdSchema::elementGroups() const +{ + const QReadLocker locker(&m_lock); + + return m_elementGroups.values(); +} + +void XsdSchema::addNotation(const XsdNotation::Ptr ¬ation) +{ + const QWriteLocker locker(&m_lock); + + m_notations.insert(notation->name(m_namePool), notation); +} + +XsdNotation::Ptr XsdSchema::notation(const QXmlName &name) const +{ + const QReadLocker locker(&m_lock); + + return m_notations.value(name); +} + +XsdNotation::List XsdSchema::notations() const +{ + const QReadLocker locker(&m_lock); + + return m_notations.values(); +} + +void XsdSchema::addIdentityConstraint(const XsdIdentityConstraint::Ptr &constraint) +{ + const QWriteLocker locker(&m_lock); + + m_identityConstraints.insert(constraint->name(m_namePool), constraint); +} + +XsdIdentityConstraint::Ptr XsdSchema::identityConstraint(const QXmlName &name) const +{ + const QReadLocker locker(&m_lock); + + return m_identityConstraints.value(name); +} + +XsdIdentityConstraint::List XsdSchema::identityConstraints() const +{ + const QReadLocker locker(&m_lock); + + return m_identityConstraints.values(); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdschema_p.h b/src/xmlpatterns/schema/qxsdschema_p.h new file mode 100644 index 0000000..b41a2d5 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdschema_p.h @@ -0,0 +1,271 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdSchema_H +#define Patternist_XsdSchema_H + +#include "qschematype_p.h" +#include "qxsdannotated_p.h" +#include "qxsdattribute_p.h" +#include "qxsdattributegroup_p.h" +#include "qxsdcomplextype_p.h" +#include "qxsdelement_p.h" +#include "qxsdidentityconstraint_p.h" +#include "qxsdmodelgroup_p.h" +#include "qxsdnotation_p.h" +#include "qxsdsimpletype_p.h" + +#include +#include + +/** + * @defgroup Patternist_schema XML Schema Processing + */ + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Represents a XSD schema object. + * + * The class provides access to all components of a parsed XSD. + * + * @note In the documentation of this class objects, which are direct + * children of the schema object, are called top-level objects. + * + * @see XML Schema API reference + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdSchema : public QSharedData, public XsdAnnotated + { + public: + typedef QExplicitlySharedDataPointer Ptr; + typedef QList List; + + /** + * Creates a new schema object. + * + * @param namePool The namepool that should be used for names of + * all schema components. + */ + XsdSchema(const NamePool::Ptr &namePool); + + /** + * Destroys the schema object. + */ + ~XsdSchema(); + + /** + * Returns the namepool that is used for names of + * all schema components. + */ + NamePool::Ptr namePool() const; + + /** + * Sets the @p targetNamespace of the schema. + */ + void setTargetNamespace(const QString &targetNamespace); + + /** + * Returns the target namespace of the schema. + */ + QString targetNamespace() const; + + /** + * Adds a new top-level @p element to the schema. + * + * @param element The new element. + * @see Element Declaration + */ + void addElement(const XsdElement::Ptr &element); + + /** + * Returns the top-level element of the schema with + * the given @p name or an empty pointer if none exist. + */ + XsdElement::Ptr element(const QXmlName &name) const; + + /** + * Returns the list of all top-level elements. + */ + XsdElement::List elements() const; + + /** + * Adds a new top-level @p attribute to the schema. + * + * @param attribute The new attribute. + * @see Attribute Declaration + */ + void addAttribute(const XsdAttribute::Ptr &attribute); + + /** + * Returns the top-level attribute of the schema with + * the given @p name or an empty pointer if none exist. + */ + XsdAttribute::Ptr attribute(const QXmlName &name) const; + + /** + * Returns the list of all top-level attributes. + */ + XsdAttribute::List attributes() const; + + /** + * Adds a new top-level @p type to the schema. + * That can be a simple or a complex type. + * + * @param type The new type. + * @see Simple Type Declaration + * @see Complex Type Declaration + */ + void addType(const SchemaType::Ptr &type); + + /** + * Returns the top-level type of the schema with + * the given @p name or an empty pointer if none exist. + */ + SchemaType::Ptr type(const QXmlName &name) const; + + /** + * Returns the list of all top-level types. + */ + SchemaType::List types() const; + + /** + * Returns the list of all top-level simple types. + */ + XsdSimpleType::List simpleTypes() const; + + /** + * Returns the list of all top-level complex types. + */ + XsdComplexType::List complexTypes() const; + + /** + * Adds an anonymous @p type to the schema. + * Anonymous types have no name and are declared + * locally inside an element object. + * + * @param type The new anonymous type. + */ + void addAnonymousType(const SchemaType::Ptr &type); + + /** + * Returns the list of all anonymous types. + */ + SchemaType::List anonymousTypes() const; + + /** + * Adds a new top-level attribute @p group to the schema. + * + * @param group The new attribute group. + * @see Attribute Group Declaration + */ + void addAttributeGroup(const XsdAttributeGroup::Ptr &group); + + /** + * Returns the top-level attribute group of the schema with + * the given @p name or an empty pointer if none exist. + */ + XsdAttributeGroup::Ptr attributeGroup(const QXmlName name) const; + + /** + * Returns the list of all top-level attribute groups. + */ + XsdAttributeGroup::List attributeGroups() const; + + /** + * Adds a new top-level element @p group to the schema. + * + * @param group The new element group. + * @see Element Group Declaration + */ + void addElementGroup(const XsdModelGroup::Ptr &group); + + /** + * Returns the top-level element group of the schema with + * the given @p name or an empty pointer if none exist. + */ + XsdModelGroup::Ptr elementGroup(const QXmlName &name) const; + + /** + * Returns the list of all top-level element groups. + */ + XsdModelGroup::List elementGroups() const; + + /** + * Adds a new top-level @p notation to the schema. + * + * @param notation The new notation. + * @see Notation Declaration + */ + void addNotation(const XsdNotation::Ptr ¬ation); + + /** + * Returns the top-level notation of the schema with + * the given @p name or an empty pointer if none exist. + */ + XsdNotation::Ptr notation(const QXmlName &name) const; + + /** + * Returns the list of all top-level notations. + */ + XsdNotation::List notations() const; + + /** + * Adds a new identity @p constraint to the schema. + */ + void addIdentityConstraint(const XsdIdentityConstraint::Ptr &constraint); + + /** + * Returns the identity constraint with the given @p name + * or an empty pointer if none exist. + */ + XsdIdentityConstraint::Ptr identityConstraint(const QXmlName &name) const; + + /** + * Returns the list of all identity constraints in this schema. + */ + XsdIdentityConstraint::List identityConstraints() const; + + private: + NamePool::Ptr m_namePool; + QString m_targetNamespace; + QHash m_elements; + QHash m_attributes; + QHash m_types; + QHash m_anonymousTypes; + QHash m_attributeGroups; + QHash m_elementGroups; + QHash m_notations; + QHash m_identityConstraints; + mutable QReadWriteLock m_lock; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsdschemachecker.cpp b/src/xmlpatterns/schema/qxsdschemachecker.cpp new file mode 100644 index 0000000..2a64327 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdschemachecker.cpp @@ -0,0 +1,2031 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qxsdschemachecker_p.h" + +#include "qderivedinteger_p.h" +#include "qderivedstring_p.h" +#include "qpatternplatform_p.h" +#include "qqnamevalue_p.h" +#include "qsourcelocationreflection_p.h" +#include "qvaluefactory_p.h" +#include "qxsdattributereference_p.h" +#include "qxsdparticlechecker_p.h" +#include "qxsdreference_p.h" +#include "qxsdschemacontext_p.h" +#include "qxsdschemahelper_p.h" +#include "qxsdschemaparsercontext_p.h" +#include "qxsdschematypesfactory_p.h" +#include "qxsdtypechecker_p.h" + +#include "qxsdschemachecker_helper.cpp" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +XsdSchemaChecker::XsdSchemaChecker(const QExplicitlySharedDataPointer &context, const XsdSchemaParserContext *parserContext) + : m_context(context) + , m_namePool(parserContext->namePool()) + , m_schema(parserContext->schema()) +{ + setupAllowedAtomicFacets(); +} + +XsdSchemaChecker::~XsdSchemaChecker() +{ +} + +/* + * This method is called after the resolver has set the base type for every + * type and information about deriavtion and 'is simple type vs. is complex type' + * are available. + */ +void XsdSchemaChecker::basicCheck() +{ + // first check that there is no circular inheritance, only the + // wxsSuperType is used here + checkBasicCircularInheritances(); + + // check the basic constraints like simple type can not inherit from complex type etc. + checkBasicSimpleTypeConstraints(); + checkBasicComplexTypeConstraints(); +} + +void XsdSchemaChecker::check() +{ + checkCircularInheritances(); + checkInheritanceRestrictions(); + checkSimpleDerivationRestrictions(); + checkSimpleTypeConstraints(); + checkComplexTypeConstraints(); + checkDuplicatedAttributeUses(); + + checkElementConstraints(); + checkAttributeConstraints(); + checkAttributeUseConstraints(); +// checkElementDuplicates(); +} + +void XsdSchemaChecker::addComponentLocationHash(const ComponentLocationHash &hash) +{ + m_componentLocationHash.unite(hash); +} + +/** + * Checks whether the @p otherType is the same as @p myType or if one of its + * ancestors is the same as @p myType. + */ +static bool matchesType(const SchemaType::Ptr &myType, const SchemaType::Ptr &otherType, QSet visitedTypes) +{ + bool retval = false; + + if (otherType) { + if (visitedTypes.contains(otherType)) { + return true; + } else { + visitedTypes.insert(otherType); + } + // simple types can have different varieties, so we have to check each of them + if (otherType->isSimpleType()) { + const XsdSimpleType::Ptr simpleType = otherType; + if (simpleType->category() == XsdSimpleType::SimpleTypeAtomic) { + // for atomic type we use the same test as in SchemaType::wxsTypeMatches + retval = (myType == simpleType ? true : matchesType(myType, simpleType->wxsSuperType(), visitedTypes)); + } else if (simpleType->category() == XsdSimpleType::SimpleTypeList) { + // for list type we test against the itemType property + retval = (myType == simpleType->itemType() ? true : matchesType(myType, simpleType->itemType()->wxsSuperType(), visitedTypes)); + } else if (simpleType->category() == XsdSimpleType::SimpleTypeUnion) { + // for union type we test against each member type + const XsdSimpleType::List members = simpleType->memberTypes(); + for (int i = 0; i < members.count(); ++i) { + if (myType == members.at(i) ? true : matchesType(myType, members.at(i)->wxsSuperType(), visitedTypes)) { + retval = true; + break; + } + } + } else { + // reached xsAnySimple type whichs category is None + retval = false; + } + } else { + // if no simple type we handle it like in SchemaType::wxsTypeMatches + retval = (myType == otherType ? true : matchesType(myType, otherType->wxsSuperType(), visitedTypes)); + } + } else // if otherType is null it doesn't match + retval = false; + + return retval; +} + +/** + * Checks whether there is a circular inheritance for the union inheritance. + */ +static bool hasCircularUnionInheritance(const XsdSimpleType::Ptr &type, const SchemaType::Ptr &otherType, NamePool::Ptr &namePool) +{ + if (type == otherType) { + return true; + } + + if (!otherType->isSimpleType() || !otherType->isDefinedBySchema()) { + return false; + } + + const XsdSimpleType::Ptr simpleOtherType = otherType; + + if (simpleOtherType->category() == XsdSimpleType::SimpleTypeUnion) { + const XsdSimpleType::List memberTypes = simpleOtherType->memberTypes(); + for (int i = 0; i < memberTypes.count(); ++i) { + if (otherType->wxsSuperType() == type) { + return true; + } + if (hasCircularUnionInheritance(type, memberTypes.at(i), namePool)) { + return true; + } + } + } + + return false; +} + +static inline bool wxsTypeMatches(const SchemaType::Ptr &type, const SchemaType::Ptr &otherType, QSet &visitedTypes, SchemaType::Ptr &conflictingType) +{ + if (!otherType) + return false; + + if (visitedTypes.contains(otherType)) { // inheritance loop detected + conflictingType = otherType; + return true; + } else { + visitedTypes.insert(otherType); + } + + if (type == otherType) + return true; + + return wxsTypeMatches(type, otherType->wxsSuperType(), visitedTypes, conflictingType); +} + +void XsdSchemaChecker::checkBasicCircularInheritances() +{ + // check all global types... + SchemaType::List types = m_schema->types(); + + // .. and anonymous types + types << m_schema->anonymousTypes(); + + for (int i = 0; i < types.count(); ++i) { + const SchemaType::Ptr type = types.at(i); + const QSourceLocation location = sourceLocationForType(type); + + // @see http://www.w3.org/TR/xmlschema11-1/#ct-props-correct 3) + + // check normal base type inheritance + QSet visitedTypes; + SchemaType::Ptr conflictingType; + + if (wxsTypeMatches(type, type->wxsSuperType(), visitedTypes, conflictingType)) { + if (conflictingType) + m_context->error(QtXmlPatterns::tr("%1 has inheritance loop in its base type %2") + .arg(formatType(m_namePool, type)) + .arg(formatType(m_namePool, conflictingType)), + XsdSchemaContext::XSDError, location); + else + m_context->error(QtXmlPatterns::tr("circular inheritance of base type %1").arg(formatType(m_namePool, type)), XsdSchemaContext::XSDError, location); + + return; + } + } +} + +void XsdSchemaChecker::checkCircularInheritances() +{ + // check all global types... + SchemaType::List types = m_schema->types(); + + // .. and anonymous types + types << m_schema->anonymousTypes(); + + for (int i = 0; i < types.count(); ++i) { + const SchemaType::Ptr type = types.at(i); + const QSourceLocation location = sourceLocationForType(type); + + // @see http://www.w3.org/TR/xmlschema11-1/#ct-props-correct 3) + + // check normal base type inheritance + QSet visitedTypes; + if (matchesType(type, type->wxsSuperType(), visitedTypes)) { + m_context->error(QtXmlPatterns::tr("circular inheritance of base type %1").arg(formatType(m_namePool, type)), XsdSchemaContext::XSDError, location); + return; + } + + // check union member inheritance + if (type->isSimpleType() && type->isDefinedBySchema()) { + const XsdSimpleType::Ptr simpleType = type; + if (simpleType->category() == XsdSimpleType::SimpleTypeUnion) { + const XsdSimpleType::List memberTypes = simpleType->memberTypes(); + for (int j = 0; j < memberTypes.count(); ++j) { + if (hasCircularUnionInheritance(simpleType, memberTypes.at(j), m_namePool)) { + m_context->error(QtXmlPatterns::tr("circular inheritance of union %1").arg(formatType(m_namePool, type)), XsdSchemaContext::XSDError, location); + return; + } + } + } + } + } +} + +void XsdSchemaChecker::checkInheritanceRestrictions() +{ + // check all global types... + SchemaType::List types = m_schema->types(); + + // .. and anonymous types + types << m_schema->anonymousTypes(); + + for (int i = 0; i < types.count(); ++i) { + const SchemaType::Ptr type = types.at(i); + const QSourceLocation location = sourceLocationForType(type); + + // check inheritance restrictions given by final property of base class + const SchemaType::Ptr baseType = type->wxsSuperType(); + if (baseType->isDefinedBySchema()) { + if ((type->derivationMethod() == SchemaType::DerivationRestriction) && (baseType->derivationConstraints() & SchemaType::RestrictionConstraint)) { + m_context->error(QtXmlPatterns::tr("%1 is not allowed to derive from %2 by restriction as the latter defines it as final") + .arg(formatType(m_namePool, type)) + .arg(formatType(m_namePool, baseType)), XsdSchemaContext::XSDError, location); + return; + } else if ((type->derivationMethod() == SchemaType::DerivationExtension) && (baseType->derivationConstraints() & SchemaType::ExtensionConstraint)) { + m_context->error(QtXmlPatterns::tr("%1 is not allowed to derive from %2 by extension as the latter defines it as final") + .arg(formatType(m_namePool, type)) + .arg(formatType(m_namePool, baseType)), XsdSchemaContext::XSDError, location); + return; + } + } + } +} + +void XsdSchemaChecker::checkBasicSimpleTypeConstraints() +{ + // check all global types... + SchemaType::List types = m_schema->types(); + + // .. and anonymous types + types << m_schema->anonymousTypes(); + + for (int i = 0; i < types.count(); ++i) { + const SchemaType::Ptr type = types.at(i); + + if (!type->isSimpleType()) + continue; + + const XsdSimpleType::Ptr simpleType = type; + + const QSourceLocation location = sourceLocation(simpleType); + + // check inheritance restrictions of simple type defined by schema constraints + const SchemaType::Ptr baseType = simpleType->wxsSuperType(); + + if (baseType->isComplexType() && (simpleType->name(m_namePool) != BuiltinTypes::xsAnySimpleType->name(m_namePool))) { + m_context->error(QtXmlPatterns::tr("base type of simple type %1 cannot be complex type %2") + .arg(formatType(m_namePool, simpleType)) + .arg(formatType(m_namePool, baseType)), + XsdSchemaContext::XSDError, location); + return; + } + + if (baseType == BuiltinTypes::xsAnyType) { + if (type->name(m_namePool) != BuiltinTypes::xsAnySimpleType->name(m_namePool)) { + m_context->error(QtXmlPatterns::tr("simple type %1 cannot have direct base type %2") + .arg(formatType(m_namePool, simpleType)) + .arg(formatType(m_namePool, BuiltinTypes::xsAnyType)), + XsdSchemaContext::XSDError, location); + return; + } + } + } +} + +void XsdSchemaChecker::checkSimpleTypeConstraints() +{ + // check all global types... + SchemaType::List types = m_schema->types(); + + // .. and anonymous types + types << m_schema->anonymousTypes(); + + for (int i = 0; i < types.count(); ++i) { + const SchemaType::Ptr type = types.at(i); + + if (!type->isSimpleType()) + continue; + + const XsdSimpleType::Ptr simpleType = type; + + const QSourceLocation location = sourceLocation(simpleType); + + if (simpleType->category() == XsdSimpleType::None) { + // additional checks + // check that no user defined type has xs:AnySimpleType as base type (except xs:AnyAtomicType) + if (simpleType->wxsSuperType()->name(m_namePool) == BuiltinTypes::xsAnySimpleType->name(m_namePool)) { + if (simpleType->name(m_namePool) != BuiltinTypes::xsAnyAtomicType->name(m_namePool)) { + m_context->error(QtXmlPatterns::tr("simple type %1 is not allowed to have base type %2") + .arg(formatType(m_namePool, simpleType)) + .arg(formatType(m_namePool, simpleType->wxsSuperType())), + XsdSchemaContext::XSDError, location); + return; + } + } + // check that no user defined type has xs:AnyAtomicType as base type + if (simpleType->wxsSuperType()->name(m_namePool) == BuiltinTypes::xsAnyAtomicType->name(m_namePool)) { + m_context->error(QtXmlPatterns::tr("simple type %1 is not allowed to have base type %2") + .arg(formatType(m_namePool, simpleType)) + .arg(formatType(m_namePool, simpleType->wxsSuperType())), + XsdSchemaContext::XSDError, location); + return; + } + } + + // @see http://www.w3.org/TR/xmlschema11-1/#d0e37310 + if (simpleType->category() == XsdSimpleType::SimpleTypeAtomic) { + // 1.1 + if ((simpleType->wxsSuperType()->category() != XsdSimpleType::SimpleTypeAtomic) && (simpleType->name(m_namePool) != BuiltinTypes::xsAnyAtomicType->name(m_namePool))) { + m_context->error(QtXmlPatterns::tr("simple type %1 can only have simple atomic type as base type") + .arg(formatType(m_namePool, simpleType)), + XsdSchemaContext::XSDError, location); + } + // 1.2 + if (simpleType->wxsSuperType()->derivationConstraints() & SchemaType::RestrictionConstraint) { + m_context->error(QtXmlPatterns::tr("simple type %1 cannot derive from %2 as the latter defines restriction as final") + .arg(formatType(m_namePool, simpleType->wxsSuperType())) + .arg(formatType(m_namePool, simpleType)), + XsdSchemaContext::XSDError, location); + } + + // 1.3 + // checked by checkConstrainingFacets already + } else if (simpleType->category() == XsdSimpleType::SimpleTypeList) { + const AnySimpleType::Ptr itemType = simpleType->itemType(); + + // 2.1 or @see http://www.w3.org/TR/xmlschema-2/#cos-list-of-atomic + if (itemType->category() != SchemaType::SimpleTypeAtomic && itemType->category() != SchemaType::SimpleTypeUnion) { + m_context->error(QtXmlPatterns::tr("variety of item type of %1 must be either atomic or union").arg(formatType(m_namePool, simpleType)), XsdSchemaContext::XSDError, location); + return; + } + + // 2.1 second part + if (itemType->category() == SchemaType::SimpleTypeUnion && itemType->isDefinedBySchema()) { + const XsdSimpleType::Ptr simpleItemType = itemType; + const AnySimpleType::List memberTypes = simpleItemType->memberTypes(); + for (int j = 0; j < memberTypes.count(); ++j) { + if (memberTypes.at(j)->category() != SchemaType::SimpleTypeAtomic) { + m_context->error(QtXmlPatterns::tr("variety of member types of %1 must be atomic").arg(formatType(m_namePool, simpleItemType)), XsdSchemaContext::XSDError, location); + return; + } + } + } + + // 2.2.1 + if (simpleType->wxsSuperType()->name(m_namePool) == BuiltinTypes::xsAnySimpleType->name(m_namePool)) { + if (itemType->isSimpleType() && itemType->isDefinedBySchema()) { + const XsdSimpleType::Ptr simpleItemType = itemType; + + // 2.2.1.1 + if (simpleItemType->derivationConstraints() & XsdSimpleType::ListConstraint) { + m_context->error(QtXmlPatterns::tr("%1 is not allowed to derive from %2 by list as the latter defines it as final") + .arg(formatType(m_namePool, simpleType)) + .arg(formatType(m_namePool, simpleItemType)), XsdSchemaContext::XSDError, location); + return; + } + + // 2.2.1.2 + const XsdFacet::Hash facets = simpleType->facets(); + XsdFacet::HashIterator it(facets); + + bool invalidFacetFound = false; + while (it.hasNext()) { + it.next(); + if (it.key() != XsdFacet::WhiteSpace) { + invalidFacetFound = true; + break; + } + } + + if (invalidFacetFound) { + m_context->error(QtXmlPatterns::tr("simple type %1 is only allowed to have %2 facet") + .arg(formatType(m_namePool, simpleType)) + .arg(formatKeyword("whiteSpace")), + XsdSchemaContext::XSDError, location); + return; + } + } + } else { // 2.2.2 + // 2.2.2.1 + if (simpleType->wxsSuperType()->category() != XsdSimpleType::SimpleTypeList) { + m_context->error(QtXmlPatterns::tr("base type of simple type %1 must have variety of type list").arg(formatType(m_namePool, simpleType)), XsdSchemaContext::XSDError, location); + return; + } + + // 2.2.2.2 + if (simpleType->wxsSuperType()->derivationConstraints() & SchemaType::RestrictionConstraint) { + m_context->error(QtXmlPatterns::tr("base type of simple type %1 has defined derivation by restriction as final").arg(formatType(m_namePool, simpleType)), XsdSchemaContext::XSDError, location); + return; + } + + // 2.2.2.3 + if (!XsdSchemaHelper::isSimpleDerivationOk(itemType, XsdSimpleType::Ptr(simpleType->wxsSuperType())->itemType(), SchemaType::DerivationConstraints())) { + m_context->error(QtXmlPatterns::tr("item type of base type does not match item type of %1").arg(formatType(m_namePool, simpleType)), XsdSchemaContext::XSDError, location); + return; + } + + // 2.2.2.4 + const XsdFacet::Hash facets = simpleType->facets(); + XsdFacet::HashIterator it(facets); + + bool invalidFacetFound = false; + XsdFacet::Type invalidFacetType = XsdFacet::None; + while (it.hasNext()) { + it.next(); + const XsdFacet::Type facetType = it.key(); + if (facetType != XsdFacet::Length && + facetType != XsdFacet::MinimumLength && + facetType != XsdFacet::MaximumLength && + facetType != XsdFacet::WhiteSpace && + facetType != XsdFacet::Pattern && + facetType != XsdFacet::Enumeration) { + invalidFacetType = facetType; + invalidFacetFound = true; + break; + } + } + + if (invalidFacetFound) { + m_context->error(QtXmlPatterns::tr("simple type %1 contains not allowed facet type %2") + .arg(formatType(m_namePool, simpleType)) + .arg(formatKeyword(XsdFacet::typeName(invalidFacetType))), + XsdSchemaContext::XSDError, location); + return; + } + + // 2.2.2.5 + // TODO: check value constraints + } + + + } else if (simpleType->category() == XsdSimpleType::SimpleTypeUnion) { + const AnySimpleType::List memberTypes = simpleType->memberTypes(); + + if (simpleType->wxsSuperType()->name(m_namePool) == BuiltinTypes::xsAnySimpleType->name(m_namePool)) { // 3.1.1 + // 3.3.1.1 + for (int i = 0; i < memberTypes.count(); ++i) { + const AnySimpleType::Ptr memberType = memberTypes.at(i); + + if (memberType->derivationConstraints() & XsdSimpleType::UnionConstraint) { + m_context->error(QtXmlPatterns::tr("%1 is not allowed to derive from %2 by union as the latter defines it as final") + .arg(formatType(m_namePool, simpleType)) + .arg(formatType(m_namePool, memberType)), XsdSchemaContext::XSDError, location); + return; + } + } + + // 3.3.1.2 + if (!simpleType->facets().isEmpty()) { + m_context->error(QtXmlPatterns::tr("%1 is not allowed to have any facets") + .arg(formatType(m_namePool, simpleType)), + XsdSchemaContext::XSDError, location); + return; + } + } else { + // 3.1.2.1 + if (simpleType->wxsSuperType()->category() != SchemaType::SimpleTypeUnion) { + m_context->error(QtXmlPatterns::tr("base type %1 of simple type %2 must have variety of union") + .arg(formatType(m_namePool, simpleType->wxsSuperType())) + .arg(formatType(m_namePool, simpleType)), + XsdSchemaContext::XSDError, location); + return; + } + + // 3.1.2.2 + if (simpleType->wxsSuperType()->derivationConstraints() & SchemaType::DerivationRestriction) { + m_context->error(QtXmlPatterns::tr("base type %1 of simple type %2 is not allowed to have restriction in %3 attribute") + .arg(formatType(m_namePool, simpleType->wxsSuperType())) + .arg(formatType(m_namePool, simpleType)) + .arg(formatAttribute("final")), + XsdSchemaContext::XSDError, location); + return; + } + + //3.1.2.3 + if (simpleType->wxsSuperType()->isDefinedBySchema()) { + const XsdSimpleType::Ptr simpleBaseType(simpleType->wxsSuperType()); + + AnySimpleType::List baseMemberTypes = simpleBaseType->memberTypes(); + for (int i = 0; i < memberTypes.count(); ++i) { + const AnySimpleType::Ptr memberType = memberTypes.at(i); + const AnySimpleType::Ptr baseMemberType = baseMemberTypes.at(i); + + if (!XsdSchemaHelper::isSimpleDerivationOk(memberType, baseMemberType, SchemaType::DerivationConstraints())) { + m_context->error(QtXmlPatterns::tr("member type %1 cannot be derived from member type %2 of %3's base type %4") + .arg(formatType(m_namePool, memberType)) + .arg(formatType(m_namePool, baseMemberType)) + .arg(formatType(m_namePool, simpleType)) + .arg(formatType(m_namePool, simpleBaseType)), + XsdSchemaContext::XSDError, location); + } + } + } + + // 3.1.2.4 + const XsdFacet::Hash facets = simpleType->facets(); + XsdFacet::HashIterator it(facets); + + bool invalidFacetFound = false; + XsdFacet::Type invalidFacetType = XsdFacet::None; + while (it.hasNext()) { + it.next(); + const XsdFacet::Type facetType = it.key(); + if (facetType != XsdFacet::Pattern && + facetType != XsdFacet::Enumeration) { + invalidFacetType = facetType; + invalidFacetFound = true; + break; + } + } + + if (invalidFacetFound) { + m_context->error(QtXmlPatterns::tr("simple type %1 contains not allowed facet type %2") + .arg(formatType(m_namePool, simpleType)) + .arg(formatKeyword(XsdFacet::typeName(invalidFacetType))), + XsdSchemaContext::XSDError, location); + return; + } + + // 3.1.2.5 + // TODO: check value constraints + } + } + } +} + +void XsdSchemaChecker::checkBasicComplexTypeConstraints() +{ + // check all global types... + SchemaType::List types = m_schema->types(); + + // .. and anonymous types + types << m_schema->anonymousTypes(); + + for (int i = 0; i < types.count(); ++i) { + const SchemaType::Ptr type = types.at(i); + + if (!type->isComplexType() || !type->isDefinedBySchema()) + continue; + + const XsdComplexType::Ptr complexType = type; + + const QSourceLocation location = sourceLocation(complexType); + + // check inheritance restrictions of complex type defined by schema constraints + const SchemaType::Ptr baseType = complexType->wxsSuperType(); + + // @see http://www.w3.org/TR/xmlschema11-1/#ct-props-correct 2) + if (baseType->isSimpleType() && (complexType->derivationMethod() != XsdComplexType::DerivationExtension)) { + m_context->error(QtXmlPatterns::tr("derivation method of %1 must be extension because the base type %2 is a simple type") + .arg(formatType(m_namePool, complexType)) + .arg(formatType(m_namePool, baseType)), + XsdSchemaContext::XSDError, location); + return; + } + } +} + +void XsdSchemaChecker::checkComplexTypeConstraints() +{ + // check all global types... + SchemaType::List types = m_schema->types(); + + // .. and anonymous types + types << m_schema->anonymousTypes(); + + for (int i = 0; i < types.count(); ++i) { + const SchemaType::Ptr type = types.at(i); + + if (!type->isComplexType() || !type->isDefinedBySchema()) + continue; + + const XsdComplexType::Ptr complexType = type; + + const QSourceLocation location = sourceLocation(complexType); + + if (complexType->contentType()->particle()) { + XsdElement::Ptr duplicatedElement; + if (XsdParticleChecker::hasDuplicatedElements(complexType->contentType()->particle(), m_namePool, duplicatedElement)) { + m_context->error(QtXmlPatterns::tr("complex type %1 has duplicated element %2 in its content model") + .arg(formatType(m_namePool, complexType)) + .arg(formatKeyword(duplicatedElement->displayName(m_namePool))), + XsdSchemaContext::XSDError, location); + return; + } + + if (!XsdParticleChecker::isUPAConform(complexType->contentType()->particle(), m_namePool)) { + m_context->error(QtXmlPatterns::tr("complex type %1 has non-deterministic content") + .arg(formatType(m_namePool, complexType)), + XsdSchemaContext::XSDError, location); + return; + } + } + + // check inheritance restrictions of complex type defined by schema constraints + const SchemaType::Ptr baseType = complexType->wxsSuperType(); + + // @see http://www.w3.org/TR/xmlschema11-1/#cos-ct-extends + if (complexType->derivationMethod() == XsdComplexType::DerivationExtension) { + if (baseType->isComplexType() && baseType->isDefinedBySchema()) { + const XsdComplexType::Ptr complexBaseType = baseType; + + // we can skip 1.1 here, as it is tested in checkInheritanceRestrictions() already + + // 1.2 and 1.3 + QString errorMsg; + if (!XsdSchemaHelper::isValidAttributeUsesExtension(complexType->attributeUses(), complexBaseType->attributeUses(), + complexType->attributeWildcard(), complexBaseType->attributeWildcard(), m_context, errorMsg)) { + m_context->error(QtXmlPatterns::tr("attributes of complex type %1 are not a valid extension of the attributes of base type %2: %3") + .arg(formatType(m_namePool, complexType)) + .arg(formatType(m_namePool, baseType)) + .arg(errorMsg), + XsdSchemaContext::XSDError, location); + return; + } + + // 1.4 + bool validContentType = false; + if (complexType->contentType()->variety() == XsdComplexType::ContentType::Simple && complexBaseType->contentType()->variety() == XsdComplexType::ContentType::Simple) { + if (complexType->contentType()->simpleType() == complexBaseType->contentType()->simpleType()) { + validContentType = true; // 1.4.1 + } + } else if (complexType->contentType()->variety() == XsdComplexType::ContentType::Empty && complexBaseType->contentType()->variety() == XsdComplexType::ContentType::Empty) { + validContentType = true; // 1.4.2 + } else { // 1.4.3 + if (complexType->contentType()->variety() == XsdComplexType::ContentType::ElementOnly || complexType->contentType()->variety() == XsdComplexType::ContentType::Mixed) { // 1.4.3.1 + if (complexBaseType->contentType()->variety() == XsdComplexType::ContentType::Empty) { + validContentType = true; // 1.4.3.2.1 + } else { // 1.4.3.2.2 + if (complexType->contentType()->particle()) { // our own check + if ((complexType->contentType()->variety() == XsdComplexType::ContentType::ElementOnly && complexBaseType->contentType()->variety() == XsdComplexType::ContentType::ElementOnly) || + (complexType->contentType()->variety() == XsdComplexType::ContentType::Mixed && complexBaseType->contentType()->variety() == XsdComplexType::ContentType::Mixed)) { // 1.4.3.2.2.1 + if (isValidParticleExtension(complexType->contentType()->particle(), complexBaseType->contentType()->particle())) { + validContentType = true; // 1.4.3.2.2.2 + } + } + } + // 1.4.3.2.2.3 and 1.4.3.2.2.4 handle 'open content' that we do not support yet + } + } + } + + // 1.5 WTF?!? + + if (!validContentType) { + m_context->error(QtXmlPatterns::tr("content model of complex type %1 is not a valid extension of content model of %2") + .arg(formatType(m_namePool, complexType)) + .arg(formatType(m_namePool, complexBaseType)), + XsdSchemaContext::XSDError, location); + return; + } + + } else if (baseType->isSimpleType()) { + // 2.1 + if (complexType->contentType()->variety() != XsdComplexType::ContentType::Simple) { + m_context->error(QtXmlPatterns::tr("complex type %1 must have simple content") + .arg(formatType(m_namePool, complexType)), + XsdSchemaContext::XSDError, location); + return; + } + + if (complexType->contentType()->simpleType() != baseType) { + m_context->error(QtXmlPatterns::tr("complex type %1 must have the same simple type as its base class %2") + .arg(formatType(m_namePool, complexType)) + .arg(formatType(m_namePool, baseType)), + XsdSchemaContext::XSDError, location); + return; + } + + // 2.2 tested in checkInheritanceRestrictions() already + } + } else if (complexType->derivationMethod() == XsdComplexType::DerivationRestriction) { + // @see http://www.w3.org/TR/xmlschema11-1/#d0e21402 + const SchemaType::Ptr baseType(complexType->wxsSuperType()); + + bool derivationOk = false; + QString errorMsg; + + // we can partly skip 1 here, as it is tested in checkInheritanceRestrictions() already + if (baseType->isComplexType()) { + + // 2.1 + if (baseType->name(m_namePool) == BuiltinTypes::xsAnyType->name(m_namePool)) { + derivationOk = true; + } + + if (baseType->isDefinedBySchema()) { + const XsdComplexType::Ptr complexBaseType(baseType); + + // 2.2.1 + if (complexType->contentType()->variety() == XsdComplexType::ContentType::Simple) { + // 2.2.2.1 + if (XsdSchemaHelper::isSimpleDerivationOk(complexType->contentType()->simpleType(), complexBaseType->contentType()->simpleType(), SchemaType::DerivationConstraints())) + derivationOk = true; + + // 2.2.2.2 + if (complexBaseType->contentType()->variety() == XsdComplexType::ContentType::Mixed) { + if (XsdSchemaHelper::isParticleEmptiable(complexBaseType->contentType()->particle())) + derivationOk = true; + } + } + + // 2.3.1 + if (complexType->contentType()->variety() == XsdComplexType::ContentType::Empty) { + // 2.3.2.1 + if (complexBaseType->contentType()->variety() == XsdComplexType::ContentType::Empty) + derivationOk = true; + + // 2.3.2.2 + if (complexBaseType->contentType()->variety() == XsdComplexType::ContentType::ElementOnly || complexBaseType->contentType()->variety() == XsdComplexType::ContentType::Mixed) { + if (XsdSchemaHelper::isParticleEmptiable(complexBaseType->contentType()->particle())) + derivationOk = true; + } + } + + // 2.4.1.1 + if (((complexType->contentType()->variety() == XsdComplexType::ContentType::ElementOnly) && + (complexBaseType->contentType()->variety() == XsdComplexType::ContentType::ElementOnly || complexBaseType->contentType()->variety() == XsdComplexType::ContentType::Mixed)) || + // 2.4.1.2 + (complexType->contentType()->variety() == XsdComplexType::ContentType::Mixed && complexBaseType->contentType()->variety() == XsdComplexType::ContentType::Mixed)) { + + // 2.4.2 + if (XsdParticleChecker::subsumes(complexBaseType->contentType()->particle(), complexType->contentType()->particle(), m_context, errorMsg)) + derivationOk = true; + } + } + } + + if (!derivationOk) { + m_context->error(QtXmlPatterns::tr("complex type %1 cannot be derived from base type %2%3") + .arg(formatType(m_namePool, complexType)) + .arg(formatType(m_namePool, baseType)) + .arg(errorMsg.isEmpty() ? QString() : QLatin1String(": ") + errorMsg), + XsdSchemaContext::XSDError, location); + return; + } + + if (baseType->isDefinedBySchema()) { + const XsdComplexType::Ptr complexBaseType(baseType); + + QString errorMsg; + if (!XsdSchemaHelper::isValidAttributeUsesRestriction(complexType->attributeUses(), complexBaseType->attributeUses(), + complexType->attributeWildcard(), complexBaseType->attributeWildcard(), m_context, errorMsg)) { + m_context->error(QtXmlPatterns::tr("attributes of complex type %1 are not a valid restriction from the attributes of base type %2: %3") + .arg(formatType(m_namePool, complexType)) + .arg(formatType(m_namePool, baseType)) + .arg(errorMsg), + XsdSchemaContext::XSDError, location); + return; + } + } + } + + // check that complex type with simple content is not allowed to inherit from + // built in complex type xs:AnyType + if (complexType->contentType()->variety() == XsdComplexType::ContentType::Simple) { + if (baseType->name(m_namePool) == BuiltinTypes::xsAnyType->name(m_namePool)) { + m_context->error(QtXmlPatterns::tr("complex type %1 with simple content cannot be derived from complex base type %2") + .arg(formatType(m_namePool, complexType)) + .arg(formatType(m_namePool, baseType)), + XsdSchemaContext::XSDError, location); + return; + } + } + } +} + +void XsdSchemaChecker::checkSimpleDerivationRestrictions() +{ + // check all global types... + SchemaType::List types = m_schema->types(); + + // .. and anonymous types + types << m_schema->anonymousTypes(); + + for (int i = 0; i < types.count(); ++i) { + const SchemaType::Ptr type = types.at(i); + + if (type->isComplexType()) + continue; + + if (type->category() != SchemaType::SimpleTypeList && type->category() != SchemaType::SimpleTypeUnion) + continue; + + const XsdSimpleType::Ptr simpleType = type; + const QSourceLocation location = sourceLocation(simpleType); + + // check all simple types derived by list + if (simpleType->category() == XsdSimpleType::SimpleTypeList) { + const AnySimpleType::Ptr itemType = simpleType->itemType(); + + if (itemType->isComplexType()) { + m_context->error(QtXmlPatterns::tr("item type of simple type %1 cannot be a complex type") + .arg(formatType(m_namePool, simpleType)), + XsdSchemaContext::XSDError, location); + return; + } + + + if (itemType->isSimpleType() && itemType->isDefinedBySchema()) { + const XsdSimpleType::Ptr simpleItemType = itemType; + if (simpleItemType->derivationConstraints() & XsdSimpleType::ListConstraint) { + m_context->error(QtXmlPatterns::tr("%1 is not allowed to derive from %2 by list as the latter defines it as final") + .arg(formatType(m_namePool, simpleType)) + .arg(formatType(m_namePool, simpleItemType)), + XsdSchemaContext::XSDError, location); + return; + } + } + + // @see http://www.w3.org/TR/xmlschema-2/#cos-list-of-atomic + if (itemType->category() != SchemaType::SimpleTypeAtomic && itemType->category() != SchemaType::SimpleTypeUnion) { + m_context->error(QtXmlPatterns::tr("variety of item type of %1 must be either atomic or union").arg(formatType(m_namePool, simpleType)), XsdSchemaContext::XSDError, location); + return; + } + + if (itemType->category() == SchemaType::SimpleTypeUnion && itemType->isDefinedBySchema()) { + const XsdSimpleType::Ptr simpleItemType = itemType; + const AnySimpleType::List memberTypes = simpleItemType->memberTypes(); + for (int j = 0; j < memberTypes.count(); ++j) { + if (memberTypes.at(j)->category() != SchemaType::SimpleTypeAtomic) { + m_context->error(QtXmlPatterns::tr("variety of member types of %1 must be atomic").arg(formatType(m_namePool, simpleItemType)), XsdSchemaContext::XSDError, location); + return; + } + } + } + } + + // check all simple types derived by union + if (simpleType->category() == XsdSimpleType::SimpleTypeUnion) { + const AnySimpleType::List memberTypes = simpleType->memberTypes(); + + for (int i = 0; i < memberTypes.count(); ++i) { + const AnySimpleType::Ptr memberType = memberTypes.at(i); + + if (memberType->isComplexType()) { + m_context->error(QtXmlPatterns::tr("member type of simple type %1 cannot be a complex type") + .arg(formatType(m_namePool, simpleType)), + XsdSchemaContext::XSDError, location); + return; + } + + // @see http://www.w3.org/TR/xmlschema-2/#cos-no-circular-unions + if (simpleType->name(m_namePool) == memberType->name(m_namePool)) { + m_context->error(QtXmlPatterns::tr("%1 is not allowed to have a member type with the same name as itself") + .arg(formatType(m_namePool, simpleType)), + XsdSchemaContext::XSDError, location); + return; + } + + if (memberType->isSimpleType() && memberType->isDefinedBySchema()) { + const XsdSimpleType::Ptr simpleMemberType = memberType; + if (simpleMemberType->derivationConstraints() & XsdSimpleType::UnionConstraint) { + m_context->error(QtXmlPatterns::tr("%1 is not allowed to derive from %2 by union as the latter defines it as final") + .arg(formatType(m_namePool, simpleType)) + .arg(formatType(m_namePool, simpleMemberType)), + XsdSchemaContext::XSDError, location); + return; + } + } + } + } + } +} + +void XsdSchemaChecker::checkConstrainingFacets() +{ + // first the global simple types + const SchemaType::List types = m_schema->types(); + for (int i = 0; i < types.count(); ++i) { + if (!(types.at(i)->isSimpleType()) || !(types.at(i)->isDefinedBySchema())) + continue; + + const XsdSimpleType::Ptr simpleType = types.at(i); + checkConstrainingFacets(simpleType->facets(), simpleType); + } + + // and afterwards all anonymous simple types + const SchemaType::List anonymousTypes = m_schema->anonymousTypes(); + for (int i = 0; i < anonymousTypes.count(); ++i) { + if (!(anonymousTypes.at(i)->isSimpleType()) || !(anonymousTypes.at(i)->isDefinedBySchema())) + continue; + + const XsdSimpleType::Ptr simpleType = anonymousTypes.at(i); + checkConstrainingFacets(simpleType->facets(), simpleType); + } +} + +void XsdSchemaChecker::checkConstrainingFacets(const XsdFacet::Hash &facets, const XsdSimpleType::Ptr &simpleType) +{ + if (facets.isEmpty()) + return; + + SchemaType::Ptr comparableBaseType; + if (!simpleType->wxsSuperType()->isDefinedBySchema()) + comparableBaseType = simpleType->wxsSuperType(); + else + comparableBaseType = simpleType->primitiveType(); + + const XsdSchemaSourceLocationReflection reflection(sourceLocation(simpleType)); + + // start checks + if (facets.contains(XsdFacet::Length)) { + const XsdFacet::Ptr lengthFacet = facets.value(XsdFacet::Length); + const DerivedInteger::Ptr lengthValue = lengthFacet->value(); + + // @see http://www.w3.org/TR/xmlschema-2/#length-minLength-maxLength + if (facets.contains(XsdFacet::MinimumLength)) { + const XsdFacet::Ptr minLengthFacet = facets.value(XsdFacet::MinimumLength); + const DerivedInteger::Ptr minLengthValue = minLengthFacet->value(); + + bool foundSuperMinimumLength = false; + SchemaType::Ptr baseType = simpleType->wxsSuperType(); + while (baseType) { + const XsdFacet::Hash baseFacets = m_context->facetsForType(baseType); + if (baseFacets.contains(XsdFacet::MinimumLength) && !baseFacets.contains(XsdFacet::Length)) { + const DerivedInteger::Ptr superValue(baseFacets.value(XsdFacet::MinimumLength)->value()); + if (minLengthValue->toInteger() == superValue->toInteger()) { + foundSuperMinimumLength = true; + break; + } + } + + baseType = baseType->wxsSuperType(); + } + + if ((minLengthValue->toInteger() > lengthValue->toInteger()) || !foundSuperMinimumLength) { + m_context->error(QtXmlPatterns::tr("%1 facet collides with %2 facet") + .arg(formatKeyword("length")) + .arg(formatKeyword("minLength")), + XsdSchemaContext::XSDError, sourceLocation(simpleType)); + return; + } + } + + // @see http://www.w3.org/TR/xmlschema-2/#length-minLength-maxLength + if (facets.contains(XsdFacet::MaximumLength)) { + const XsdFacet::Ptr maxLengthFacet = facets.value(XsdFacet::MaximumLength); + const DerivedInteger::Ptr maxLengthValue = maxLengthFacet->value(); + + bool foundSuperMaximumLength = false; + SchemaType::Ptr baseType = simpleType->wxsSuperType(); + while (baseType) { + const XsdFacet::Hash baseFacets = m_context->facetsForType(baseType); + if (baseFacets.contains(XsdFacet::MaximumLength) && !baseFacets.contains(XsdFacet::Length)) { + const DerivedInteger::Ptr superValue(baseFacets.value(XsdFacet::MaximumLength)->value()); + if (maxLengthValue->toInteger() == superValue->toInteger()) { + foundSuperMaximumLength = true; + break; + } + } + + baseType = baseType->wxsSuperType(); + } + + if ((maxLengthValue->toInteger() < lengthValue->toInteger()) || !foundSuperMaximumLength) { + m_context->error(QtXmlPatterns::tr("%1 facet collides with %2 facet") + .arg(formatKeyword("length")) + .arg(formatKeyword("maxLength")), + XsdSchemaContext::XSDError, sourceLocation(simpleType)); + return; + } + } + + // @see http://www.w3.org/TR/xmlschema-2/#length-valid-restriction + if (simpleType->derivationMethod() == XsdSimpleType::DerivationRestriction) { + const XsdFacet::Hash baseFacets = m_context->facetsForType(simpleType->wxsSuperType()); + if (baseFacets.contains(XsdFacet::Length)) { + const DerivedInteger::Ptr baseValue = baseFacets.value(XsdFacet::Length)->value(); + if (lengthValue->toInteger() != baseValue->toInteger()) { + m_context->error(QtXmlPatterns::tr("%1 facet must have the same value as %2 facet of base type") + .arg(formatKeyword("length")) + .arg(formatKeyword("length")), + XsdSchemaContext::XSDError, sourceLocation(simpleType)); + return; + } + } + } + } + + if (facets.contains(XsdFacet::MinimumLength)) { + const XsdFacet::Ptr minLengthFacet = facets.value(XsdFacet::MinimumLength); + const DerivedInteger::Ptr minLengthValue = minLengthFacet->value(); + + if (facets.contains(XsdFacet::MaximumLength)) { + const XsdFacet::Ptr maxLengthFacet = facets.value(XsdFacet::MaximumLength); + const DerivedInteger::Ptr maxLengthValue = maxLengthFacet->value(); + + // @see http://www.w3.org/TR/xmlschema-2/#minLength-less-than-equal-to-maxLength + if (maxLengthValue->toInteger() < minLengthValue->toInteger()) { + m_context->error(QtXmlPatterns::tr("%1 facet collides with %2 facet") + .arg(formatKeyword("minLength")) + .arg(formatKeyword("maxLength")), + XsdSchemaContext::XSDError, sourceLocation(simpleType)); + return; + } + + // @see http://www.w3.org/TR/xmlschema-2/#minLength-valid-restriction + //TODO: check parent facets + } + + // @see http://www.w3.org/TR/xmlschema-2/#minLength-valid-restriction + if (simpleType->derivationMethod() == XsdSimpleType::DerivationRestriction) { + const XsdFacet::Hash baseFacets = m_context->facetsForType(simpleType->wxsSuperType()); + if (baseFacets.contains(XsdFacet::MinimumLength)) { + const DerivedInteger::Ptr baseValue = baseFacets.value(XsdFacet::MinimumLength)->value(); + if (minLengthValue->toInteger() < baseValue->toInteger()) { + m_context->error(QtXmlPatterns::tr("%1 facet must be equal or greater than %2 facet of base type") + .arg(formatKeyword("minLength")) + .arg(formatKeyword("minLength")), + XsdSchemaContext::XSDError, sourceLocation(simpleType)); + return; + } + } + } + } + if (facets.contains(XsdFacet::MaximumLength)) { + const XsdFacet::Ptr maxLengthFacet = facets.value(XsdFacet::MaximumLength); + const DerivedInteger::Ptr maxLengthValue = maxLengthFacet->value(); + + // @see http://www.w3.org/TR/xmlschema-2/#maxLength-valid-restriction + if (simpleType->derivationMethod() == XsdSimpleType::DerivationRestriction) { + const XsdFacet::Hash baseFacets = m_context->facetsForType(simpleType->wxsSuperType()); + if (baseFacets.contains(XsdFacet::MaximumLength)) { + const DerivedInteger::Ptr baseValue(baseFacets.value(XsdFacet::MaximumLength)->value()); + if (maxLengthValue->toInteger() > baseValue->toInteger()) { + m_context->error(QtXmlPatterns::tr("%1 facet must be less than or equal to %2 facet of base type") + .arg(formatKeyword("maxLength")) + .arg(formatKeyword("maxLength")), + XsdSchemaContext::XSDError, sourceLocation(simpleType)); + return; + } + } + } + } + if (facets.contains(XsdFacet::Pattern)) { + // we keep the patterns in separated facets + // @see http://www.w3.org/TR/xmlschema-2/#src-multiple-patterns + + // @see http://www.w3.org/TR/xmlschema-2/#cvc-pattern-valid + const XsdFacet::Ptr patternFacet = facets.value(XsdFacet::Pattern); + const AtomicValue::List multiValue = patternFacet->multiValue(); + + for (int i = 0; i < multiValue.count(); ++i) { + const DerivedString::Ptr value = multiValue.at(i); + const QRegExp exp = PatternPlatform::parsePattern(value->stringValue(), m_context, &reflection); + if (!exp.isValid()) { + m_context->error(QtXmlPatterns::tr("%1 facet contains invalid regular expression").arg(formatKeyword("pattern")), XsdSchemaContext::XSDError, sourceLocation(simpleType)); + return; + } + } + } + if (facets.contains(XsdFacet::Enumeration)) { + // @see http://www.w3.org/TR/xmlschema-2/#src-multiple-enumerations + + const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration); + + if (BuiltinTypes::xsNOTATION->wxsTypeMatches(simpleType)) { + const AtomicValue::List notationNames = facet->multiValue(); + for (int k = 0; k < notationNames.count(); ++k) { + const QNameValue::Ptr notationName = notationNames.at(k); + if (!m_schema->notation(notationName->qName())) { + m_context->error(QtXmlPatterns::tr("unknown notation %1 used in %2 facet") + .arg(formatKeyword(m_namePool, notationName->qName())) + .arg(formatKeyword("enumeration")), + XsdSchemaContext::XSDError, sourceLocation(simpleType)); + } + } + } else if (BuiltinTypes::xsQName->wxsTypeMatches(simpleType)) { + } else { + const XsdTypeChecker checker(m_context, QVector(), sourceLocation(simpleType)); + + const AnySimpleType::Ptr baseType = simpleType->wxsSuperType(); + const XsdFacet::Hash baseFacets = XsdTypeChecker::mergedFacetsForType(baseType, m_context); + + const AtomicValue::List multiValue = facet->multiValue(); + for (int k = 0; k < multiValue.count(); ++k) { + const QString stringValue = multiValue.at(k)->as >()->stringValue(); + const QString actualValue = XsdTypeChecker::normalizedValue(stringValue, baseFacets); + + QString errorMsg; + if (!checker.isValidString(actualValue, baseType, errorMsg)) { + m_context->error(QtXmlPatterns::tr("%1 facet contains invalid value %2: %3") + .arg(formatKeyword("enumeration")) + .arg(formatData(stringValue)) + .arg(errorMsg), + XsdSchemaContext::XSDError, sourceLocation(simpleType)); + return; + } + } + } + } + if (facets.contains(XsdFacet::WhiteSpace)) { + const XsdFacet::Ptr whiteSpaceFacet = facets.value(XsdFacet::WhiteSpace); + const DerivedString::Ptr whiteSpaceValue = whiteSpaceFacet->value(); + + // @see http://www.w3.org/TR/xmlschema-2/#whiteSpace-valid-restriction + if (simpleType->derivationMethod() == XsdSimpleType::DerivationRestriction) { + const XsdFacet::Hash baseFacets = m_context->facetsForType(simpleType->wxsSuperType()); + if (baseFacets.contains(XsdFacet::WhiteSpace)) { + const QString value = whiteSpaceValue->stringValue(); + const QString baseValue = DerivedString::Ptr(baseFacets.value(XsdFacet::WhiteSpace)->value())->stringValue(); + if (value == XsdSchemaToken::toString(XsdSchemaToken::Replace) || value == XsdSchemaToken::toString(XsdSchemaToken::Preserve)) { + if (baseValue == XsdSchemaToken::toString(XsdSchemaToken::Collapse)) { + m_context->error(QtXmlPatterns::tr("%1 facet cannot be %2 or %3 if %4 facet of base type is %5") + .arg(formatKeyword("whiteSpace")) + .arg(formatData("replace")) + .arg(formatData("preserve")) + .arg(formatKeyword("whiteSpace")) + .arg(formatData("collapse")), + XsdSchemaContext::XSDError, sourceLocation(simpleType)); + return; + } + } + if (value == XsdSchemaToken::toString(XsdSchemaToken::Preserve) && baseValue == XsdSchemaToken::toString(XsdSchemaToken::Replace)) { + m_context->error(QtXmlPatterns::tr("%1 facet cannot be %2 if %3 facet of base type is %4") + .arg(formatKeyword("whiteSpace")) + .arg(formatData("preserve")) + .arg(formatKeyword("whiteSpace")) + .arg(formatData("replace")), + XsdSchemaContext::XSDError, sourceLocation(simpleType)); + return; + } + } + } + } + if (facets.contains(XsdFacet::MaximumInclusive)) { + const XsdFacet::Ptr maxFacet = facets.value(XsdFacet::MaximumInclusive); + + // @see http://www.w3.org/TR/xmlschema-2/#minInclusive-less-than-equal-to-maxInclusive + if (facets.contains(XsdFacet::MinimumInclusive)) { + const XsdFacet::Ptr minFacet = facets.value(XsdFacet::MinimumInclusive); + + if (comparableBaseType) { + if (XsdSchemaHelper::constructAndCompare(minFacet->value(), AtomicComparator::OperatorGreaterThan, maxFacet->value(), comparableBaseType, m_context, &reflection)) { + m_context->error(QtXmlPatterns::tr("%1 facet must be less than or equal to %2 facet") + .arg(formatKeyword("minInclusive")) + .arg(formatKeyword("maxInclusive")), + XsdSchemaContext::XSDError, sourceLocation(simpleType)); + return; + } + } + } + + // @see http://www.w3.org/TR/xmlschema-2/#maxInclusive-valid-restriction + if (simpleType->derivationMethod() == XsdSimpleType::DerivationRestriction) { + const XsdFacet::Hash baseFacets = m_context->facetsForType(simpleType->wxsSuperType()); + if (baseFacets.contains(XsdFacet::MaximumInclusive)) { + const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::MaximumInclusive); + if (comparableBaseType) { + if (XsdSchemaHelper::constructAndCompare(maxFacet->value(), AtomicComparator::OperatorGreaterThan, baseFacet->value(), comparableBaseType, m_context, &reflection)) { + m_context->error(QtXmlPatterns::tr("%1 facet must be less than or equal to %2 facet of base type") + .arg(formatKeyword("maxInclusive")) + .arg(formatKeyword("maxInclusive")), + XsdSchemaContext::XSDError, sourceLocation(simpleType)); + return; + } + } + } + if (baseFacets.contains(XsdFacet::MaximumExclusive)) { + const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::MaximumExclusive); + if (comparableBaseType) { + if (XsdSchemaHelper::constructAndCompare(maxFacet->value(), AtomicComparator::OperatorGreaterOrEqual, baseFacet->value(), comparableBaseType, m_context, &reflection)) { + m_context->error(QtXmlPatterns::tr("%1 facet must be less than %2 facet of base type") + .arg(formatKeyword("maxInclusive")) + .arg(formatKeyword("maxExclusive")), + XsdSchemaContext::XSDError, sourceLocation(simpleType)); + return; + } + } + } + } + } + if (facets.contains(XsdFacet::MaximumExclusive)) { + const XsdFacet::Ptr maxFacet = facets.value(XsdFacet::MaximumExclusive); + + // @see http://www.w3.org/TR/xmlschema-2/#maxInclusive-maxExclusive + if (facets.contains(XsdFacet::MaximumInclusive)) { + m_context->error(QtXmlPatterns::tr("%1 facet and %2 facet cannot appear together") + .arg(formatKeyword("maxExclusive")) + .arg(formatKeyword("maxInclusive")), + XsdSchemaContext::XSDError, sourceLocation(simpleType)); + return; + } + + // @see http://www.w3.org/TR/xmlschema-2/#minExclusive-less-than-equal-to-maxExclusive + if (facets.contains(XsdFacet::MinimumExclusive)) { + const XsdFacet::Ptr minFacet = facets.value(XsdFacet::MinimumExclusive); + if (comparableBaseType) { + if (XsdSchemaHelper::constructAndCompare(minFacet->value(), AtomicComparator::OperatorGreaterThan, maxFacet->value(), comparableBaseType, m_context, &reflection)) { + m_context->error(QtXmlPatterns::tr("%1 facet must be less than or equal to %2 facet") + .arg(formatKeyword("minExclusive")) + .arg(formatKeyword("maxExclusive")), + XsdSchemaContext::XSDError, sourceLocation(simpleType)); + return; + } + } + } + + // @see http://www.w3.org/TR/xmlschema-2/#maxExclusive-valid-restriction + if (simpleType->derivationMethod() == XsdSimpleType::DerivationRestriction) { + const XsdFacet::Hash baseFacets = m_context->facetsForType(simpleType->wxsSuperType()); + if (baseFacets.contains(XsdFacet::MaximumExclusive)) { + const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::MaximumExclusive); + if (comparableBaseType) { + if (XsdSchemaHelper::constructAndCompare(maxFacet->value(), AtomicComparator::OperatorGreaterThan, baseFacet->value(), comparableBaseType, m_context, &reflection)) { + m_context->error(QtXmlPatterns::tr("%1 facet must be less than or equal to %2 facet of base type") + .arg(formatKeyword("maxExclusive")) + .arg(formatKeyword("maxExclusive")), + XsdSchemaContext::XSDError, sourceLocation(simpleType)); + return; + } + } + } + if (baseFacets.contains(XsdFacet::MaximumInclusive)) { + const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::MaximumInclusive); + if (comparableBaseType) { + if (XsdSchemaHelper::constructAndCompare(maxFacet->value(), AtomicComparator::OperatorGreaterThan, baseFacet->value(), comparableBaseType, m_context, &reflection)) { + m_context->error(QtXmlPatterns::tr("%1 facet must be less than or equal to %2 facet of base type") + .arg(formatKeyword("maxExclusive")) + .arg(formatKeyword("maxInclusive")), + XsdSchemaContext::XSDError, sourceLocation(simpleType)); + return; + } + } + } + if (baseFacets.contains(XsdFacet::MinimumInclusive)) { + const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::MinimumInclusive); + if (comparableBaseType) { + if (XsdSchemaHelper::constructAndCompare(maxFacet->value(), AtomicComparator::OperatorLessOrEqual, baseFacet->value(), comparableBaseType, m_context, &reflection)) { + m_context->error(QtXmlPatterns::tr("%1 facet must be greater than %2 facet of base type") + .arg(formatKeyword("maxExclusive")) + .arg(formatKeyword("minInclusive")), + XsdSchemaContext::XSDError, sourceLocation(simpleType)); + return; + } + } + } + if (baseFacets.contains(XsdFacet::MinimumExclusive)) { + const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::MinimumExclusive); + if (comparableBaseType) { + if (XsdSchemaHelper::constructAndCompare(maxFacet->value(), AtomicComparator::OperatorLessOrEqual, baseFacet->value(), comparableBaseType, m_context, &reflection)) { + m_context->error(QtXmlPatterns::tr("%1 facet must be greater than %2 facet of base type") + .arg(formatKeyword("maxExclusive")) + .arg(formatKeyword("minExclusive")), + XsdSchemaContext::XSDError, sourceLocation(simpleType)); + return; + } + } + } + } + } + if (facets.contains(XsdFacet::MinimumExclusive)) { + const XsdFacet::Ptr minFacet = facets.value(XsdFacet::MinimumExclusive); + + // @see http://www.w3.org/TR/xmlschema-2/#minInclusive-minExclusive + if (facets.contains(XsdFacet::MinimumInclusive)) { + m_context->error(QtXmlPatterns::tr("%1 facet and %2 facet cannot appear together") + .arg(formatKeyword("minExclusive")) + .arg(formatKeyword("minInclusive")), + XsdSchemaContext::XSDError, sourceLocation(simpleType)); + return; + } + + // @see http://www.w3.org/TR/xmlschema-2/#minExclusive-less-than-maxInclusive + if (facets.contains(XsdFacet::MaximumInclusive)) { + const XsdFacet::Ptr maxFacet = facets.value(XsdFacet::MaximumInclusive); + if (comparableBaseType) { + if (XsdSchemaHelper::constructAndCompare(minFacet->value(), AtomicComparator::OperatorGreaterOrEqual, maxFacet->value(), comparableBaseType, m_context, &reflection)) { + m_context->error(QtXmlPatterns::tr("%1 facet must be less than %2 facet") + .arg(formatKeyword("minExclusive")) + .arg(formatKeyword("maxInclusive")), + XsdSchemaContext::XSDError, sourceLocation(simpleType)); + return; + } + } + } + + // @see http://www.w3.org/TR/xmlschema-2/#minExclusive-valid-restriction + if (simpleType->derivationMethod() == XsdSimpleType::DerivationRestriction) { + const XsdFacet::Hash baseFacets = m_context->facetsForType(simpleType->wxsSuperType()); + if (baseFacets.contains(XsdFacet::MinimumExclusive)) { + const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::MinimumExclusive); + if (comparableBaseType) { + if (XsdSchemaHelper::constructAndCompare(minFacet->value(), AtomicComparator::OperatorLessThan, baseFacet->value(), comparableBaseType, m_context, &reflection)) { + m_context->error(QtXmlPatterns::tr("%1 facet must be greater than or equal to %2 facet of base type") + .arg(formatKeyword("minExclusive")) + .arg(formatKeyword("minExclusive")), + XsdSchemaContext::XSDError, sourceLocation(simpleType)); + return; + } + } + } + if (baseFacets.contains(XsdFacet::MaximumExclusive)) { + const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::MaximumExclusive); + if (comparableBaseType) { + if (XsdSchemaHelper::constructAndCompare(minFacet->value(), AtomicComparator::OperatorGreaterOrEqual, baseFacet->value(), comparableBaseType, m_context, &reflection)) { + m_context->error(QtXmlPatterns::tr("%1 facet must be less than %2 facet of base type") + .arg(formatKeyword("minExclusive")) + .arg(formatKeyword("maxExclusive")), + XsdSchemaContext::XSDError, sourceLocation(simpleType)); + return; + } + } + } + if (baseFacets.contains(XsdFacet::MaximumInclusive)) { + const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::MaximumInclusive); + if (comparableBaseType) { + if (XsdSchemaHelper::constructAndCompare(minFacet->value(), AtomicComparator::OperatorGreaterThan, baseFacet->value(), comparableBaseType, m_context, &reflection)) { + m_context->error(QtXmlPatterns::tr("%1 facet must be less than or equal to %2 facet of base type") + .arg(formatKeyword("minExclusive")) + .arg(formatKeyword("maxInclusive")), + XsdSchemaContext::XSDError, sourceLocation(simpleType)); + return; + } + } + } + } + } + if (facets.contains(XsdFacet::MinimumInclusive)) { + const XsdFacet::Ptr minFacet = facets.value(XsdFacet::MinimumInclusive); + + // @see http://www.w3.org/TR/xmlschema-2/#minInclusive-less-than-maxExclusive + if (facets.contains(XsdFacet::MaximumExclusive)) { + const XsdFacet::Ptr maxFacet = facets.value(XsdFacet::MaximumExclusive); + if (comparableBaseType) { + if (XsdSchemaHelper::constructAndCompare(minFacet->value(), AtomicComparator::OperatorGreaterOrEqual, maxFacet->value(), comparableBaseType, m_context, &reflection)) { + m_context->error(QtXmlPatterns::tr("%1 facet must be less than %2 facet") + .arg(formatKeyword("minInclusive")) + .arg(formatKeyword("maxExclusive")), + XsdSchemaContext::XSDError, sourceLocation(simpleType)); + return; + } + } + } + + // @see http://www.w3.org/TR/xmlschema-2/#minInclusive-valid-restriction + if (simpleType->derivationMethod() == XsdSimpleType::DerivationRestriction) { + const XsdFacet::Hash baseFacets = m_context->facetsForType(simpleType->wxsSuperType()); + if (baseFacets.contains(XsdFacet::MinimumInclusive)) { + const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::MinimumInclusive); + if (comparableBaseType) { + if (XsdSchemaHelper::constructAndCompare(minFacet->value(), AtomicComparator::OperatorLessThan, baseFacet->value(), comparableBaseType, m_context, &reflection)) { + m_context->error(QtXmlPatterns::tr("%1 facet must be greater than or equal to %2 facet of base type") + .arg(formatKeyword("minInclusive")) + .arg(formatKeyword("minInclusive")), + XsdSchemaContext::XSDError, sourceLocation(simpleType)); + return; + } + } + } + if (baseFacets.contains(XsdFacet::MinimumExclusive)) { + const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::MinimumExclusive); + if (comparableBaseType) { + if (XsdSchemaHelper::constructAndCompare(minFacet->value(), AtomicComparator::OperatorLessOrEqual, baseFacet->value(), comparableBaseType, m_context, &reflection)) { + m_context->error(QtXmlPatterns::tr("%1 facet must be greater than %2 facet of base type") + .arg(formatKeyword("minInclusive")) + .arg(formatKeyword("minExclusive")), + XsdSchemaContext::XSDError, sourceLocation(simpleType)); + return; + } + } + } + if (baseFacets.contains(XsdFacet::MaximumInclusive)) { + const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::MaximumInclusive); + if (comparableBaseType) { + if (XsdSchemaHelper::constructAndCompare(minFacet->value(), AtomicComparator::OperatorGreaterThan, baseFacet->value(), comparableBaseType, m_context, &reflection)) { + m_context->error(QtXmlPatterns::tr("%1 facet must be less than or equal to %2 facet of base type") + .arg(formatKeyword("minInclusive")) + .arg(formatKeyword("maxInclusive")), + XsdSchemaContext::XSDError, sourceLocation(simpleType)); + return; + } + } + } + if (baseFacets.contains(XsdFacet::MaximumExclusive)) { + const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::MaximumExclusive); + if (comparableBaseType) { + if (XsdSchemaHelper::constructAndCompare(minFacet->value(), AtomicComparator::OperatorGreaterOrEqual, baseFacet->value(), comparableBaseType, m_context, &reflection)) { + m_context->error(QtXmlPatterns::tr("%1 facet must be less than %2 facet of base type") + .arg(formatKeyword("minInclusive")) + .arg(formatKeyword("maxExclusive")), + XsdSchemaContext::XSDError, sourceLocation(simpleType)); + return; + } + } + } + } + } + if (facets.contains(XsdFacet::TotalDigits)) { + const XsdFacet::Ptr totalDigitsFacet = facets.value(XsdFacet::TotalDigits); + const DerivedInteger::Ptr totalDigitsValue = totalDigitsFacet->value(); + + // @see http://www.w3.org/TR/xmlschema-2/#totalDigits-valid-restriction + if (simpleType->derivationMethod() == XsdSimpleType::DerivationRestriction) { + const XsdFacet::Hash baseFacets = m_context->facetsForType(simpleType->wxsSuperType()); + if (baseFacets.contains(XsdFacet::TotalDigits)) { + const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::TotalDigits); + const DerivedInteger::Ptr baseValue = baseFacet->value(); + + if (totalDigitsValue->toInteger() > baseValue->toInteger()) { + m_context->error(QtXmlPatterns::tr("%1 facet must be less than or equal to %2 facet of base type") + .arg(formatKeyword("totalDigits")) + .arg(formatKeyword("totalDigits")), + XsdSchemaContext::XSDError, sourceLocation(simpleType)); + return; + } + } + } + } + if (facets.contains(XsdFacet::FractionDigits)) { + const XsdFacet::Ptr fractionDigitsFacet = facets.value(XsdFacet::FractionDigits); + const DerivedInteger::Ptr fractionDigitsValue = fractionDigitsFacet->value(); + + // http://www.w3.org/TR/xmlschema-2/#fractionDigits-totalDigits + if (facets.contains(XsdFacet::TotalDigits)) { + const XsdFacet::Ptr totalDigitsFacet = facets.value(XsdFacet::TotalDigits); + const DerivedInteger::Ptr totalDigitsValue = totalDigitsFacet->value(); + + if (fractionDigitsValue->toInteger() > totalDigitsValue->toInteger()) { + m_context->error(QtXmlPatterns::tr("%1 facet must be less than or equal to %2 facet") + .arg(formatKeyword("fractionDigits")) + .arg(formatKeyword("totalDigits")), + XsdSchemaContext::XSDError, sourceLocation(simpleType)); + return; + } + } + + // @see http://www.w3.org/TR/xmlschema-2/#fractionDigits-valid-restriction + if (simpleType->derivationMethod() == XsdSimpleType::DerivationRestriction) { + const XsdFacet::Hash baseFacets = m_context->facetsForType(simpleType->wxsSuperType()); + if (baseFacets.contains(XsdFacet::FractionDigits)) { + const XsdFacet::Ptr baseFacet = baseFacets.value(XsdFacet::FractionDigits); + const DerivedInteger::Ptr baseValue = baseFacet->value(); + + if (fractionDigitsValue->toInteger() > baseValue->toInteger()) { + m_context->error(QtXmlPatterns::tr("%1 facet must be less than or equal to %2 facet of base type") + .arg(formatKeyword("fractionDigits")) + .arg(formatKeyword("fractionDigits")), + XsdSchemaContext::XSDError, sourceLocation(simpleType)); + return; + } + } + } + } + + + // check whether facets are allowed for simple types variety + if (simpleType->wxsSuperType()->category() == SchemaType::SimpleTypeAtomic) { + if (simpleType->primitiveType()) { + const QXmlName primitiveTypeName = simpleType->primitiveType()->name(m_namePool); + if (m_allowedAtomicFacets.contains(primitiveTypeName)) { + const QSet allowedFacets = m_allowedAtomicFacets.value(primitiveTypeName); + QSet availableFacets = facets.keys().toSet(); + + if (!availableFacets.subtract(allowedFacets).isEmpty()) { + m_context->error(QtXmlPatterns::tr("simple type contains not allowed facet %1") + .arg(formatKeyword(XsdFacet::typeName(availableFacets.toList().first()))), + XsdSchemaContext::XSDError, sourceLocation(simpleType)); + return; + } + } + } + } else if (simpleType->wxsSuperType()->category() == SchemaType::SimpleTypeList) { + if (facets.contains(XsdFacet::MaximumInclusive) || facets.contains(XsdFacet::MinimumInclusive) || + facets.contains(XsdFacet::MaximumExclusive) || facets.contains(XsdFacet::MinimumExclusive) || + facets.contains(XsdFacet::TotalDigits) || facets.contains(XsdFacet::FractionDigits)) + { + m_context->error(QtXmlPatterns::tr("%1, %2, %3, %4, %5 and %6 facets are not allowed when derived by list") + .arg(formatKeyword("maxInclusive")) + .arg(formatKeyword("maxExclusive")) + .arg(formatKeyword("minInclusive")) + .arg(formatKeyword("minExclusive")) + .arg(formatKeyword("totalDigits")) + .arg(formatKeyword("fractionDigits")), + XsdSchemaContext::XSDError, sourceLocation(simpleType)); + } + } else if (simpleType->wxsSuperType()->category() == SchemaType::SimpleTypeUnion) { + if (facets.contains(XsdFacet::MaximumInclusive) || facets.contains(XsdFacet::MinimumInclusive) || + facets.contains(XsdFacet::MaximumExclusive) || facets.contains(XsdFacet::MinimumExclusive) || + facets.contains(XsdFacet::TotalDigits) || facets.contains(XsdFacet::FractionDigits) || + facets.contains(XsdFacet::MinimumLength) || facets.contains(XsdFacet::MaximumLength) || + facets.contains(XsdFacet::Length) || facets.contains(XsdFacet::WhiteSpace)) + { + m_context->error(QtXmlPatterns::tr("only %1 and %2 facets are allowed when derived by union") + .arg(formatKeyword("pattern")) + .arg(formatKeyword("enumeration")), + XsdSchemaContext::XSDError, sourceLocation(simpleType)); + } + } + + // check whether value of facet matches the value space of the simple types base type + const SchemaType::Ptr baseType = simpleType->wxsSuperType(); + if (!baseType->isDefinedBySchema()) { + const XsdSchemaSourceLocationReflection reflection(sourceLocation(simpleType)); + + XsdFacet::HashIterator it(facets); + while (it.hasNext()) { + it.next(); + const XsdFacet::Ptr facet = it.value(); + if (facet->type() == XsdFacet::MaximumInclusive || + facet->type() == XsdFacet::MaximumExclusive || + facet->type() == XsdFacet::MinimumInclusive || + facet->type() == XsdFacet::MinimumExclusive) { + const DerivedString::Ptr stringValue = facet->value(); + const AtomicValue::Ptr value = ValueFactory::fromLexical(stringValue->stringValue(), baseType, m_context, &reflection); + if (value->hasError()) { + m_context->error(QtXmlPatterns::tr("%1 contains %2 facet with invalid data: %3") + .arg(formatType(m_namePool, simpleType)) + .arg(formatKeyword(XsdFacet::typeName(facet->type()))) + .arg(formatData(stringValue->stringValue())), + XsdSchemaContext::XSDError, sourceLocation(simpleType)); + return; + } + } + + // @see http://www.w3.org/TR/xmlschema-2/#enumeration-valid-restriction + if (facet->type() == XsdFacet::Enumeration && baseType != BuiltinTypes::xsNOTATION) { + const AtomicValue::List multiValue = facet->multiValue(); + for (int j = 0; j < multiValue.count(); ++j) { + const QString stringValue = DerivedString::Ptr(multiValue.at(j))->stringValue(); + const AtomicValue::Ptr value = ValueFactory::fromLexical(stringValue, baseType, m_context, &reflection); + if (value->hasError()) { + m_context->error(QtXmlPatterns::tr("%1 contains %2 facet with invalid data: %3") + .arg(formatType(m_namePool, simpleType)) + .arg(formatKeyword(XsdFacet::typeName(XsdFacet::Enumeration))) + .arg(formatData(stringValue)), + XsdSchemaContext::XSDError, sourceLocation(simpleType)); + return; + } + } + } + } + } +} + +void XsdSchemaChecker::checkDuplicatedAttributeUses() +{ + // first all global attribute groups + const XsdAttributeGroup::List attributeGroups = m_schema->attributeGroups(); + for (int i = 0; i < attributeGroups.count(); ++i) { + const XsdAttributeGroup::Ptr attributeGroup = attributeGroups.at(i); + const XsdAttributeUse::List uses = attributeGroup->attributeUses(); + + // @see http://www.w3.org/TR/xmlschema11-1/#ct-props-correct 4) + XsdAttribute::Ptr conflictingAttribute; + if (hasDuplicatedAttributeUses(uses, conflictingAttribute)) { + m_context->error(QtXmlPatterns::tr("attribute group %1 contains attribute %2 twice") + .arg(formatKeyword(attributeGroup->displayName(m_namePool))) + .arg(formatKeyword(conflictingAttribute->displayName(m_namePool))), + XsdSchemaContext::XSDError, sourceLocation(attributeGroup)); + return; + } + + // @see http://www.w3.org/TR/xmlschema11-1/#ct-props-correct 5) + if (hasMultipleIDAttributeUses(uses)) { + m_context->error(QtXmlPatterns::tr("attribute group %1 contains two different attributes that both have types derived from %2") + .arg(formatKeyword(attributeGroup->displayName(m_namePool))) + .arg(formatType(m_namePool, BuiltinTypes::xsID)), + XsdSchemaContext::XSDError, sourceLocation(attributeGroup)); + return; + } + + if (hasConstraintIDAttributeUse(uses, conflictingAttribute)) { + m_context->error(QtXmlPatterns::tr("attribute group %1 contains attribute %2 that has value constraint but type that inherits from %3") + .arg(formatKeyword(attributeGroup->displayName(m_namePool))) + .arg(formatKeyword(conflictingAttribute->displayName(m_namePool))) + .arg(formatType(m_namePool, BuiltinTypes::xsID)), + XsdSchemaContext::XSDError, sourceLocation(attributeGroup)); + return; + } + } + + // then the global and anonymous complex types + SchemaType::List types = m_schema->types(); + types << m_schema->anonymousTypes(); + + for (int i = 0; i < types.count(); ++i) { + if (!(types.at(i)->isComplexType()) || !types.at(i)->isDefinedBySchema()) + continue; + + const XsdComplexType::Ptr complexType = types.at(i); + const XsdAttributeUse::List attributeUses = complexType->attributeUses(); + + // @see http://www.w3.org/TR/xmlschema11-1/#ct-props-correct 4) + XsdAttribute::Ptr conflictingAttribute; + if (hasDuplicatedAttributeUses(attributeUses, conflictingAttribute)) { + m_context->error(QtXmlPatterns::tr("complex type %1 contains attribute %2 twice") + .arg(formatType(m_namePool, complexType)) + .arg(formatKeyword(conflictingAttribute->displayName(m_namePool))), + XsdSchemaContext::XSDError, sourceLocation(complexType)); + return; + } + + // @see http://www.w3.org/TR/xmlschema11-1/#ct-props-correct 5) + if (hasMultipleIDAttributeUses(attributeUses)) { + m_context->error(QtXmlPatterns::tr("complex type %1 contains two different attributes that both have types derived from %2") + .arg(formatType(m_namePool, complexType)) + .arg(formatType(m_namePool, BuiltinTypes::xsID)), + XsdSchemaContext::XSDError, sourceLocation(complexType)); + return; + } + + if (hasConstraintIDAttributeUse(attributeUses, conflictingAttribute)) { + m_context->error(QtXmlPatterns::tr("complex type %1 contains attribute %2 that has value constraint but type that inherits from %3") + .arg(formatType(m_namePool, complexType)) + .arg(formatKeyword(conflictingAttribute->displayName(m_namePool))) + .arg(formatType(m_namePool, BuiltinTypes::xsID)), + XsdSchemaContext::XSDError, sourceLocation(complexType)); + return; + } + } +} + +void XsdSchemaChecker::checkElementConstraints() +{ + const QSet elements = collectAllElements(m_schema); + QSetIterator it(elements); + while (it.hasNext()) { + const XsdElement::Ptr element = it.next(); + + // @see http://www.w3.org/TR/xmlschema11-1/#e-props-correct + + // 2 and xs:ID check + if (element->valueConstraint()) { + const SchemaType::Ptr type = element->type(); + + AnySimpleType::Ptr targetType; + if (type->isSimpleType() && type->category() == SchemaType::SimpleTypeAtomic) { + targetType = type; + + // if it is a XsdSimpleType, use its primitive type as target type + if (type->isDefinedBySchema()) + targetType = XsdSimpleType::Ptr(type)->primitiveType(); + + } else if (type->isComplexType() && type->isDefinedBySchema()) { + const XsdComplexType::Ptr complexType(type); + + if (complexType->contentType()->variety() == XsdComplexType::ContentType::Simple) { + const AnySimpleType::Ptr simpleType = complexType->contentType()->simpleType(); + if (simpleType->category() == AnySimpleType::SimpleTypeAtomic) { + targetType = simpleType; + + if (simpleType->isDefinedBySchema()) + targetType = XsdSimpleType::Ptr(simpleType)->primitiveType(); + } + } else if (complexType->contentType()->variety() != XsdComplexType::ContentType::Mixed) { + m_context->error(QtXmlPatterns::tr("element %1 is not allowed to have a value constraint if its base type is complex") + .arg(formatKeyword(element->displayName(m_namePool))), + XsdSchemaContext::XSDError, sourceLocation(element)); + return; + } + } + if ((targetType == BuiltinTypes::xsID) || BuiltinTypes::xsID->wxsTypeMatches(type)) { + m_context->error(QtXmlPatterns::tr("element %1 is not allowed to have a value constraint if its type is derived from %2") + .arg(formatKeyword(element->displayName(m_namePool))) + .arg(formatType(m_namePool, BuiltinTypes::xsID)), + XsdSchemaContext::XSDError, sourceLocation(element)); + return; + } + + if (type->isSimpleType()) { + QString errorMsg; + if (!isValidValue(element->valueConstraint()->value(), type, errorMsg)) { + m_context->error(QtXmlPatterns::tr("value constraint of element %1 is not of elements type: %2") + .arg(formatKeyword(element->displayName(m_namePool))) + .arg(errorMsg), + XsdSchemaContext::XSDError, sourceLocation(element)); + return; + } + } else if (type->isComplexType() && type->isDefinedBySchema()) { + const XsdComplexType::Ptr complexType(type); + if (complexType->contentType()->variety() == XsdComplexType::ContentType::Simple) { + QString errorMsg; + if (!isValidValue(element->valueConstraint()->value(), complexType->contentType()->simpleType(), errorMsg)) { + m_context->error(QtXmlPatterns::tr("value constraint of element %1 is not of elements type: %2") + .arg(formatKeyword(element->displayName(m_namePool))) + .arg(errorMsg), + XsdSchemaContext::XSDError, sourceLocation(element)); + return; + } + } + } + } + + if (!element->substitutionGroupAffiliations().isEmpty()) { + // 3 + if (!element->scope() || element->scope()->variety() != XsdElement::Scope::Global) { + m_context->error(QtXmlPatterns::tr("element %1 is not allowed to have substitution group affiliation as it is no global element").arg(formatKeyword(element->displayName(m_namePool))), + XsdSchemaContext::XSDError, sourceLocation(element)); + return; + } + + // 4 + const XsdElement::List affiliations = element->substitutionGroupAffiliations(); + for (int i = 0; i < affiliations.count(); ++i) { + const XsdElement::Ptr affiliation = affiliations.at(i); + + bool derivationOk = false; + if (element->type()->isComplexType() && affiliation->type()->isComplexType()) { + if (XsdSchemaHelper::isComplexDerivationOk(element->type(), affiliation->type(), affiliation->substitutionGroupExclusions())) { + derivationOk = true; + } + } + if (element->type()->isComplexType() && affiliation->type()->isSimpleType()) { + if (XsdSchemaHelper::isComplexDerivationOk(element->type(), affiliation->type(), affiliation->substitutionGroupExclusions())) { + derivationOk = true; + } + } + if (element->type()->isSimpleType()) { + if (XsdSchemaHelper::isSimpleDerivationOk(element->type(), affiliation->type(), affiliation->substitutionGroupExclusions())) { + derivationOk = true; + } + } + + if (!derivationOk) { + m_context->error(QtXmlPatterns::tr("type of element %1 cannot be derived from type of substitution group affiliation").arg(formatKeyword(element->displayName(m_namePool))), + XsdSchemaContext::XSDError, sourceLocation(element)); + return; + } + } + + // 5 was checked in XsdSchemaResolver::resolveSubstitutionGroupAffiliations() already + } + } +} + +void XsdSchemaChecker::checkAttributeConstraints() +{ + // all global attributes + XsdAttribute::List attributes = m_schema->attributes(); + + // and all local attributes + SchemaType::List types = m_schema->types(); + types << m_schema->anonymousTypes(); + + for (int i = 0; i < types.count(); ++i) { + if (!types.at(i)->isComplexType() || !types.at(i)->isDefinedBySchema()) + continue; + + const XsdComplexType::Ptr complexType(types.at(i)); + const XsdAttributeUse::List uses = complexType->attributeUses(); + for (int j = 0; j < uses.count(); ++j) + attributes.append(uses.at(j)->attribute()); + } + + for (int i = 0; i < attributes.count(); ++i) { + const XsdAttribute::Ptr attribute = attributes.at(i); + + if (!attribute->valueConstraint()) + continue; + + if (attribute->valueConstraint()->variety() == XsdAttribute::ValueConstraint::Default || attribute->valueConstraint()->variety() == XsdAttribute::ValueConstraint::Fixed) { + const SchemaType::Ptr type = attribute->type(); + + QString errorMsg; + if (!isValidValue(attribute->valueConstraint()->value(), attribute->type(), errorMsg)) { + m_context->error(QtXmlPatterns::tr("value constraint of attribute %1 is not of attributes type: %2") + .arg(formatKeyword(attribute->displayName(m_namePool))) + .arg(errorMsg), + XsdSchemaContext::XSDError, sourceLocation(attribute)); + return; + } + } + + if (BuiltinTypes::xsID->wxsTypeMatches(attribute->type())) { + m_context->error(QtXmlPatterns::tr("attribute %1 has value constraint but has type derived from %2") + .arg(formatKeyword(attribute->displayName(m_namePool))) + .arg(formatType(m_namePool, BuiltinTypes::xsID)), + XsdSchemaContext::XSDError, sourceLocation(attribute)); + return; + } + } +} + +bool XsdSchemaChecker::isValidValue(const QString &stringValue, const AnySimpleType::Ptr &type, QString &errorMsg) const +{ + if (BuiltinTypes::xsAnySimpleType->name(m_namePool) == type->name(m_namePool)) + return true; // no need to check xs:anyType content + + const XsdFacet::Hash facets = XsdTypeChecker::mergedFacetsForType(type, m_context); + const QString actualValue = XsdTypeChecker::normalizedValue(stringValue, facets); + + const XsdTypeChecker checker(m_context, QVector(), QSourceLocation(QUrl(QLatin1String("http://dummy.org")), 1, 1)); + return checker.isValidString(actualValue, type, errorMsg); +} + +void XsdSchemaChecker::checkAttributeUseConstraints() +{ + XsdComplexType::List complexTypes; + + SchemaType::List types = m_schema->types(); + types << m_schema->anonymousTypes(); + + for (int i = 0; i < types.count(); ++i) { + const SchemaType::Ptr type = types.at(i); + if (type->isComplexType() && type->isDefinedBySchema()) + complexTypes.append(XsdComplexType::Ptr(type)); + } + + for (int i = 0; i < complexTypes.count(); ++i) { + const XsdComplexType::Ptr complexType(complexTypes.at(i)); + const SchemaType::Ptr baseType = complexType->wxsSuperType(); + if (!baseType || !baseType->isComplexType() || !baseType->isDefinedBySchema()) + continue; + + const XsdComplexType::Ptr complexBaseType(baseType); + + const XsdAttributeUse::List attributeUses = complexType->attributeUses(); + QHash lookupHash; + for (int j = 0; j < attributeUses.count(); ++j) + lookupHash.insert(attributeUses.at(j)->attribute()->name(m_namePool), attributeUses.at(j)); + + const XsdAttributeUse::List baseAttributeUses = complexBaseType->attributeUses(); + for (int j = 0; j < baseAttributeUses.count(); ++j) { + const XsdAttributeUse::Ptr baseAttributeUse = baseAttributeUses.at(j); + + if (lookupHash.contains(baseAttributeUse->attribute()->name(m_namePool))) { + const XsdAttributeUse::Ptr attributeUse = lookupHash.value(baseAttributeUse->attribute()->name(m_namePool)); + + if (baseAttributeUse->useType() == XsdAttributeUse::RequiredUse) { + if (attributeUse->useType() == XsdAttributeUse::OptionalUse || attributeUse->useType() == XsdAttributeUse::ProhibitedUse) { + m_context->error(QtXmlPatterns::tr("%1 attribute in derived complex type must be %2 like in base type") + .arg(formatAttribute("use")) + .arg(formatData("required")), + XsdSchemaContext::XSDError, sourceLocation(complexType)); + return; + } + } + + if (baseAttributeUse->valueConstraint()) { + if (baseAttributeUse->valueConstraint()->variety() == XsdAttributeUse::ValueConstraint::Fixed) { + if (!attributeUse->valueConstraint()) { + m_context->error(QtXmlPatterns::tr("attribute %1 in derived complex type must have %2 value constraint like in base type") + .arg(formatKeyword(attributeUse->attribute()->displayName(m_namePool))) + .arg(formatData("fixed")), + XsdSchemaContext::XSDError, sourceLocation(complexType)); + return; + } else { + if (attributeUse->valueConstraint()->variety() == XsdAttributeUse::ValueConstraint::Fixed) { + const XsdTypeChecker checker(m_context, QVector(), sourceLocation(complexType)); + if (!checker.valuesAreEqual(attributeUse->valueConstraint()->value(), baseAttributeUse->valueConstraint()->value(), attributeUse->attribute()->type())) { + m_context->error(QtXmlPatterns::tr("attribute %1 in derived complex type must have the same %2 value constraint like in base type") + .arg(formatKeyword(attributeUse->attribute()->displayName(m_namePool))) + .arg(formatData("fixed")), + XsdSchemaContext::XSDError, sourceLocation(complexType)); + return; + } + } else { + m_context->error(QtXmlPatterns::tr("attribute %1 in derived complex type must have %2 value constraint") + .arg(formatKeyword(attributeUse->attribute()->displayName(m_namePool))) + .arg(formatData("fixed")), + XsdSchemaContext::XSDError, sourceLocation(complexType)); + return; + } + } + } + } + } + } + + // additional check that process content property of attribute wildcard in derived type is + // not weaker than the wildcard in base type + const XsdWildcard::Ptr baseWildcard(complexBaseType->attributeWildcard()); + const XsdWildcard::Ptr derivedWildcard(complexType->attributeWildcard()); + if (baseWildcard && derivedWildcard) { + if (!XsdSchemaHelper::checkWildcardProcessContents(baseWildcard, derivedWildcard)) { + m_context->error(QtXmlPatterns::tr("processContent of base wildcard must be weaker than derived wildcard"), XsdSchemaContext::XSDError, sourceLocation(complexType)); + return; + } + } + } +} + +void XsdSchemaChecker::checkElementDuplicates() +{ + // check all global types... + SchemaType::List types = m_schema->types(); + + // .. and anonymous types + types << m_schema->anonymousTypes(); + + for (int i = 0; i < types.count(); ++i) { + const SchemaType::Ptr type = types.at(i); + + if (!type->isComplexType() || !type->isDefinedBySchema()) + continue; + + const XsdComplexType::Ptr complexType(type); + + if ((complexType->contentType()->variety() == XsdComplexType::ContentType::ElementOnly) || (complexType->contentType()->variety() == XsdComplexType::ContentType::Mixed)) { + DuplicatedElementMap elementMap; + DuplicatedWildcardMap wildcardMap; + + checkElementDuplicates(complexType->contentType()->particle(), elementMap, wildcardMap); + } + } +} + +void XsdSchemaChecker::checkElementDuplicates(const XsdParticle::Ptr &particle, DuplicatedElementMap &elementMap, DuplicatedWildcardMap &wildcardMap) +{ + if (particle->term()->isElement()) { + const XsdElement::Ptr element(particle->term()); + + if (elementMap.contains(element->name(m_namePool))) { + if (element->type() != elementMap.value(element->name(m_namePool))) { + m_context->error(QtXmlPatterns::tr("element %1 exists twice with different types") + .arg(formatKeyword(element->displayName(m_namePool))), + XsdSchemaContext::XSDError, sourceLocation(element)); + return; + } + } else { + elementMap.insert(element->name(m_namePool), element->type()); + } + + // check substitution group affiliation + const XsdElement::List substElements = element->substitutionGroupAffiliations(); + for (int i = 0; i < substElements.count(); ++i) { + const XsdElement::Ptr substElement = substElements.at(i); + if (elementMap.contains(substElement->name(m_namePool))) { + if (substElement->type() != elementMap.value(substElement->name(m_namePool))) { + m_context->error(QtXmlPatterns::tr("element %1 exists twice with different types") + .arg(formatKeyword(substElement->displayName(m_namePool))), + XsdSchemaContext::XSDError, sourceLocation(element)); + return; + } + } else { + elementMap.insert(substElement->name(m_namePool), substElement->type()); + } + } + } else if (particle->term()->isModelGroup()) { + const XsdModelGroup::Ptr group(particle->term()); + const XsdParticle::List particles = group->particles(); + for (int i = 0; i < particles.count(); ++i) + checkElementDuplicates(particles.at(i), elementMap, wildcardMap); + } else if (particle->term()->isWildcard()) { + const XsdWildcard::Ptr wildcard(particle->term()); + + bool error = false; + if (!wildcardMap.contains(wildcard->namespaceConstraint()->variety())) { + if (!wildcardMap.isEmpty()) + error = true; + } else { + const XsdWildcard::Ptr otherWildcard = wildcardMap.value(wildcard->namespaceConstraint()->variety()); + if ((wildcard->processContents() != otherWildcard->processContents()) || (wildcard->namespaceConstraint()->namespaces() != otherWildcard->namespaceConstraint()->namespaces())) + error = true; + } + + if (error) { + m_context->error(QtXmlPatterns::tr("particle contains non-deterministic wildcards"), XsdSchemaContext::XSDError, sourceLocation(wildcard)); + return; + } else { + wildcardMap.insert(wildcard->namespaceConstraint()->variety(), wildcard); + } + } +} + +QSourceLocation XsdSchemaChecker::sourceLocation(const NamedSchemaComponent::Ptr &component) const +{ + if (m_componentLocationHash.contains(component)) { + return m_componentLocationHash.value(component); + } else { + QSourceLocation location; + location.setLine(1); + location.setColumn(1); + location.setUri(QString::fromLatin1("dummyUri")); + + return location; + } +} + +QSourceLocation XsdSchemaChecker::sourceLocationForType(const SchemaType::Ptr &type) const +{ + if (type->isSimpleType()) + return sourceLocation(XsdSimpleType::Ptr(type)); + else + return sourceLocation(XsdComplexType::Ptr(type)); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdschemachecker_helper.cpp b/src/xmlpatterns/schema/qxsdschemachecker_helper.cpp new file mode 100644 index 0000000..98c4c63 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdschemachecker_helper.cpp @@ -0,0 +1,276 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +bool XsdSchemaChecker::hasDuplicatedAttributeUses(const XsdAttributeUse::List &list, XsdAttribute::Ptr &conflictingAttribute) const +{ + const int length = list.count(); + + for (int i = 0; i < length; ++i) { + for (int j = 0; j < length; ++j) { + if (i == j) + continue; + + if (list.at(i)->attribute()->name(m_namePool) == list.at(j)->attribute()->name(m_namePool)) { + conflictingAttribute = list.at(i)->attribute(); + return true; + } + } + } + + return false; +} + +bool XsdSchemaChecker::hasMultipleIDAttributeUses(const XsdAttributeUse::List &list) const +{ + const int length = list.count(); + + bool hasIdDerivedAttribute = false; + for (int i = 0; i < length; ++i) { + if (BuiltinTypes::xsID->wxsTypeMatches(list.at(i)->attribute()->type())) { + if (hasIdDerivedAttribute) + return true; + else + hasIdDerivedAttribute = true; + } + } + + return false; +} + +bool XsdSchemaChecker::hasConstraintIDAttributeUse(const XsdAttributeUse::List &list, XsdAttribute::Ptr &conflictingAttribute) const +{ + const int length = list.count(); + + for (int i = 0; i < length; ++i) { + const XsdAttributeUse::Ptr attributeUse(list.at(i)); + if (BuiltinTypes::xsID->wxsTypeMatches(attributeUse->attribute()->type())) { + if (attributeUse->valueConstraint()) { + conflictingAttribute = attributeUse->attribute(); + return true; + } + } + } + + return false; +} + +bool XsdSchemaChecker::particleEqualsRecursively(const XsdParticle::Ptr &particle, const XsdParticle::Ptr &otherParticle) const +{ + // @see http://www.w3.org/TR/xmlschema11-1/#cos-particle-extend + //TODO: find out what 'properties' of a particle should be checked here... + + if (particle->minimumOccurs() != otherParticle->minimumOccurs()) + return false; + + if (particle->maximumOccursUnbounded() != otherParticle->maximumOccursUnbounded()) + return false; + + if (particle->maximumOccurs() != otherParticle->maximumOccurs()) + return false; + + const XsdTerm::Ptr term = particle->term(); + const XsdTerm::Ptr otherTerm = otherParticle->term(); + + if (term->isElement() && !(otherTerm->isElement())) + return false; + + if (term->isModelGroup() && !(otherTerm->isModelGroup())) + return false; + + if (term->isWildcard() && !(otherTerm->isWildcard())) + return false; + + if (term->isElement()) { + const XsdElement::Ptr element = term; + const XsdElement::Ptr otherElement = otherTerm; + + if (element->name(m_namePool) != otherElement->name(m_namePool)) + return false; + + if (element->type()->name(m_namePool) != otherElement->type()->name(m_namePool)) + return false; + } + + if (term->isModelGroup()) { + const XsdModelGroup::Ptr group = term; + const XsdModelGroup::Ptr otherGroup = otherTerm; + + if (group->particles().count() != otherGroup->particles().count()) + return false; + + for (int i = 0; i < group->particles().count(); ++i) { + if (!particleEqualsRecursively(group->particles().at(i), otherGroup->particles().at(i))) + return false; + } + } + + if (term->isWildcard()) { + } + + return true; +} + +bool XsdSchemaChecker::isValidParticleExtension(const XsdParticle::Ptr &extension, const XsdParticle::Ptr &base) const +{ + // @see http://www.w3.org/TR/xmlschema11-1/#cos-particle-extend + + // 1 + if (extension == base) + return true; + + // 2 + if (extension->minimumOccurs() == 1 && extension->maximumOccurs() == 1 && extension->maximumOccursUnbounded() == false) { + if (extension->term()->isModelGroup()) { + const XsdModelGroup::Ptr modelGroup = extension->term(); + if (modelGroup->compositor() == XsdModelGroup::SequenceCompositor) { + if (particleEqualsRecursively(modelGroup->particles().first(), base)) + return true; + } + } + } + + // 3 + if (extension->minimumOccurs() == base->minimumOccurs()) { // 3.1 + if (extension->term()->isModelGroup() && base->term()->isModelGroup()) { + const XsdModelGroup::Ptr extensionGroup(extension->term()); + const XsdModelGroup::Ptr baseGroup(base->term()); + + if (extensionGroup->compositor() == XsdModelGroup::AllCompositor && baseGroup->compositor() == XsdModelGroup::AllCompositor) { + const XsdParticle::List extensionParticles = extensionGroup->particles(); + const XsdParticle::List baseParticles = baseGroup->particles(); + for (int i = 0; i < baseParticles.count() && i < extensionParticles.count(); ++i) { + if (baseParticles.at(i) != extensionParticles.at(i)) + return false; + } + } + } + } + + return false; +} + +QSet collectAllElements(const XsdParticle::Ptr &particle) +{ + QSet elements; + + const XsdTerm::Ptr term(particle->term()); + if (term->isElement()) { + elements.insert(XsdElement::Ptr(term)); + } else if (term->isModelGroup()) { + const XsdModelGroup::Ptr group(term); + + for (int i = 0; i < group->particles().count(); ++i) + elements.unite(collectAllElements(group->particles().at(i))); + } + + return elements; +} + +QSet collectAllElements(const XsdSchema::Ptr &schema) +{ + QSet elements; + + // collect global elements + const XsdElement::List elementList = schema->elements(); + for (int i = 0; i < elementList.count(); ++i) + elements.insert(elementList.at(i)); + + // collect all elements from global groups + const XsdModelGroup::List groupList = schema->elementGroups(); + for (int i = 0; i < groupList.count(); ++i) { + const XsdModelGroup::Ptr group(groupList.at(i)); + + for (int j = 0; j < group->particles().count(); ++j) + elements.unite(collectAllElements(group->particles().at(j))); + } + + // collect all elements from complex type definitions + SchemaType::List types; + types << schema->types() << schema->anonymousTypes(); + + for (int i = 0; i < types.count(); ++i) { + if (types.at(i)->isComplexType() && types.at(i)->isDefinedBySchema()) { + const XsdComplexType::Ptr complexType(types.at(i)); + if (complexType->contentType()->particle()) + elements.unite(collectAllElements(complexType->contentType()->particle())); + } + } + + return elements; +} + +bool XsdSchemaChecker::elementSequenceAccepted(const XsdModelGroup::Ptr &sequence, const XsdParticle::Ptr &particle) const +{ + // @see http://www.w3.org/TR/xmlschema11-1/#cvc-accept + + if (particle->term()->isWildcard()) { // 1 + const XsdWildcard::Ptr wildcard(particle->term()); + + // 1.1 + if ((unsigned int)sequence->particles().count() < particle->minimumOccurs()) + return false; + + // 1.2 + if (!particle->maximumOccursUnbounded()) { + if ((unsigned int)sequence->particles().count() > particle->maximumOccurs()) + return false; + } + + // 1.3 + const XsdParticle::List particles(sequence->particles()); + for (int i = 0; i < particles.count(); ++i) { + if (particles.at(i)->term()->isElement()) { + if (!XsdSchemaHelper::wildcardAllowsExpandedName(XsdElement::Ptr(particles.at(i)->term())->name(m_namePool), wildcard, m_namePool)) + return false; + } + } + } else if (particle->term()->isElement()) { // 2 + const XsdElement::Ptr element(particle->term()); + + // 2.1 + if ((unsigned int)sequence->particles().count() < particle->minimumOccurs()) + return false; + + // 2.2 + if (!particle->maximumOccursUnbounded()) { + if ((unsigned int)sequence->particles().count() > particle->maximumOccurs()) + return false; + } + + // 2.3 + const XsdParticle::List particles(sequence->particles()); + for (int i = 0; i < particles.count(); ++i) { + bool isValid = false; + if (particles.at(i)->term()->isElement()) { + const XsdElement::Ptr seqElement(particles.at(i)->term()); + + // 2.3.1 + if (element->name(m_namePool) == seqElement->name(m_namePool)) + isValid = true; + + // 2.3.2 + if (element->scope() && element->scope()->variety() == XsdElement::Scope::Global) { + if (!(element->disallowedSubstitutions() & NamedSchemaComponent::SubstitutionConstraint)) { + //TODO: continue + } + } + } + } + } + + return true; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdschemachecker_p.h b/src/xmlpatterns/schema/qxsdschemachecker_p.h new file mode 100644 index 0000000..65fb87f --- /dev/null +++ b/src/xmlpatterns/schema/qxsdschemachecker_p.h @@ -0,0 +1,254 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdSchemaChecker_H +#define Patternist_XsdSchemaChecker_H + +#include "qschematype_p.h" +#include "qxsdattribute_p.h" +#include "qxsdattributegroup_p.h" +#include "qxsdelement_p.h" +#include "qxsdmodelgroup_p.h" +#include "qxsdnotation_p.h" +#include "qxsdschema_p.h" +#include "qxsdsimpletype_p.h" + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + class XsdSchemaContext; + class XsdSchemaParserContext; + + /** + * @short Encapsulates the checking of schema valitity after reference resolving has finished. + * + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdSchemaChecker : public QSharedData + { + public: + typedef QExplicitlySharedDataPointer Ptr; + + /** + * Creates a new schema checker. + * + * @param context The context that is used for customization. + * @param parserContext The context that contains all the data structures. + */ + XsdSchemaChecker(const QExplicitlySharedDataPointer &context, const XsdSchemaParserContext *parserContext); + + /** + * Destroys the schema checker. + */ + ~XsdSchemaChecker(); + + /** + * Starts a basic check process. + * + * This check only validates the basic super type inheritance + * of simple and complex types. + */ + void basicCheck(); + + /** + * Starts the real check process. + */ + void check(); + + /** + * Checks the constraining facets of all global and anonymous simple types for validity. + */ + void checkConstrainingFacets(); + + /** + * Adds the component location hash, so the checker is able to report meaning full + * error messages. + */ + void addComponentLocationHash(const QHash &hash); + + private: + void checkSimpleRestrictionBaseType(); + + /** + * Checks that no simple or complex type inherits itself. + */ + void checkBasicCircularInheritances(); + + /** + * Checks the advanced circular inheritance. + */ + void checkCircularInheritances(); + + /** + * Checks for inheritance restrictions given by final or finalDefault + * attributes. + */ + void checkInheritanceRestrictions(); + + /** + * Checks for various constraints for simple types defined by schema. + */ + void checkBasicSimpleTypeConstraints(); + void checkSimpleTypeConstraints(); + + /** + * Checks for various constraints for complex types defined by schema. + */ + void checkBasicComplexTypeConstraints(); + void checkComplexTypeConstraints(); + + /** + * Checks for list and union derivation restrictions given by final or finalDefault + * attributes. + */ + void checkSimpleDerivationRestrictions(); + + /** + * Checks the set of constraining @p facets that belongs to @p simpleType for validity. + */ + void checkConstrainingFacets(const XsdFacet::Hash &facets, const XsdSimpleType::Ptr &simpleType); + + /** + * Checks for duplicated attribute uses (attributes with the same name) inside a complex type. + */ + void checkDuplicatedAttributeUses(); + + /** + * Check the element constraints. + */ + void checkElementConstraints(); + + /** + * Check the attribute constraints. + */ + void checkAttributeConstraints(); + + /** + * Check the attribute use constraints. + */ + void checkAttributeUseConstraints(); + + /** + * A map used to find duplicated elements inside a model group. + */ + typedef QHash DuplicatedElementMap; + + /** + * A map used to find duplicated wildcards inside a model group. + */ + typedef QHash DuplicatedWildcardMap; + + /** + * Check for duplicated elements and element wildcards in all complex type particles. + */ + void checkElementDuplicates(); + + /** + * Check for duplicated elements and element wildcards in the given @p particle. + * + * @param particle The particle to check. + * @param elementMap A map to find the duplicated elements. + * @param wildcardMap A map to find the duplicated element wildcards. + */ + void checkElementDuplicates(const XsdParticle::Ptr &particle, DuplicatedElementMap &elementMap, DuplicatedWildcardMap &wildcardMap); + + /** + * Setup fast lookup list for allowed facets of atomic simple types. + */ + void setupAllowedAtomicFacets(); + + /** + * Returns the source location of the given schema @p component or a dummy + * source location if the component is not found in the component location hash. + */ + QSourceLocation sourceLocation(const NamedSchemaComponent::Ptr &component) const; + + /** + * Returns the source location of the given schema @p type or a dummy + * source location if the type is not found in the component location hash. + */ + QSourceLocation sourceLocationForType(const SchemaType::Ptr &type) const; + + /** + * Checks that the string @p value is valid according the value space of @p type + * for the given @p component. + */ + bool isValidValue(const QString &value, const AnySimpleType::Ptr &type, QString &errorMsg) const; + + /** + * Returns the list of facets for the given @p type. + */ + XsdFacet::Hash facetsForType(const SchemaType::Ptr &type) const; + + /** + * Returns whether the given @p list of attribute uses contains two (or more) attribute + * uses that point to attributes with the same name. @p conflictingAttribute + * will contain the conflicting attribute in that case. + */ + bool hasDuplicatedAttributeUses(const XsdAttributeUse::List &list, XsdAttribute::Ptr &conflictingAttribute) const; + + /** + * Returns whether the given @p list of attribute uses contains two (or more) attribute + * uses that have a type inherited by xs:ID. + */ + bool hasMultipleIDAttributeUses(const XsdAttributeUse::List &list) const; + + /** + * Returns whether the given @p list of attribute uses contains an attribute + * uses that has a type inherited by xs:ID with a value constraint. @p conflictingAttribute + * will contain the conflicting attribute in that case. + */ + bool hasConstraintIDAttributeUse(const XsdAttributeUse::List &list, XsdAttribute::Ptr &conflictingAttribute) const; + + /** + * Checks whether the @p particle equals the @p otherParticle recursively. + */ + bool particleEqualsRecursively(const XsdParticle::Ptr &particle, const XsdParticle::Ptr &otherParticle) const; + + /** + * Checks whether the @p extension particle is a valid extension of the @p base particle. + */ + bool isValidParticleExtension(const XsdParticle::Ptr &extension, const XsdParticle::Ptr &base) const; + + /** + * Checks whether the @p sequence of elements is accepted by the given @p particle. + */ + bool elementSequenceAccepted(const XsdModelGroup::Ptr &sequence, const XsdParticle::Ptr &particle) const; + + QExplicitlySharedDataPointer m_context; + NamePool::Ptr m_namePool; + XsdSchema::Ptr m_schema; + QHash > m_allowedAtomicFacets; + QHash m_componentLocationHash; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsdschemachecker_setup.cpp b/src/xmlpatterns/schema/qxsdschemachecker_setup.cpp new file mode 100644 index 0000000..b027129 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdschemachecker_setup.cpp @@ -0,0 +1,287 @@ + +#include "qxsdschemachecker_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +void XsdSchemaChecker::setupAllowedAtomicFacets() +{ + // string + { + QSet facets; + facets << XsdFacet::Length + << XsdFacet::MinimumLength + << XsdFacet::MaximumLength + << XsdFacet::Pattern + << XsdFacet::Enumeration + << XsdFacet::WhiteSpace + << XsdFacet::Assertion; + + m_allowedAtomicFacets.insert(BuiltinTypes::xsString->name(m_namePool), facets); + } + + // boolean + { + QSet facets; + facets << XsdFacet::Pattern + << XsdFacet::WhiteSpace + << XsdFacet::Assertion; + + m_allowedAtomicFacets.insert(BuiltinTypes::xsBoolean->name(m_namePool), facets); + } + + // float + { + QSet facets; + facets << XsdFacet::Pattern + << XsdFacet::Enumeration + << XsdFacet::WhiteSpace + << XsdFacet::MaximumInclusive + << XsdFacet::MaximumExclusive + << XsdFacet::MinimumInclusive + << XsdFacet::MinimumExclusive + << XsdFacet::Assertion; + + m_allowedAtomicFacets.insert(BuiltinTypes::xsFloat->name(m_namePool), facets); + } + + // double + { + QSet facets; + facets << XsdFacet::Pattern + << XsdFacet::Enumeration + << XsdFacet::WhiteSpace + << XsdFacet::MaximumInclusive + << XsdFacet::MaximumExclusive + << XsdFacet::MinimumInclusive + << XsdFacet::MinimumExclusive + << XsdFacet::Assertion; + + m_allowedAtomicFacets.insert(BuiltinTypes::xsDouble->name(m_namePool), facets); + } + + // decimal + { + QSet facets; + facets << XsdFacet::TotalDigits + << XsdFacet::FractionDigits + << XsdFacet::Pattern + << XsdFacet::Enumeration + << XsdFacet::WhiteSpace + << XsdFacet::MaximumInclusive + << XsdFacet::MaximumExclusive + << XsdFacet::MinimumInclusive + << XsdFacet::MinimumExclusive + << XsdFacet::Assertion; + + m_allowedAtomicFacets.insert(BuiltinTypes::xsDecimal->name(m_namePool), facets); + } + + // duration + { + QSet facets; + facets << XsdFacet::Pattern + << XsdFacet::Enumeration + << XsdFacet::WhiteSpace + << XsdFacet::MaximumInclusive + << XsdFacet::MaximumExclusive + << XsdFacet::MinimumInclusive + << XsdFacet::MinimumExclusive + << XsdFacet::Assertion; + + m_allowedAtomicFacets.insert(BuiltinTypes::xsDuration->name(m_namePool), facets); + } + + // dateTime + { + QSet facets; + facets << XsdFacet::Pattern + << XsdFacet::Enumeration + << XsdFacet::WhiteSpace + << XsdFacet::MaximumInclusive + << XsdFacet::MaximumExclusive + << XsdFacet::MinimumInclusive + << XsdFacet::MinimumExclusive + << XsdFacet::Assertion; + + m_allowedAtomicFacets.insert(BuiltinTypes::xsDateTime->name(m_namePool), facets); + } + + // time + { + QSet facets; + facets << XsdFacet::Pattern + << XsdFacet::Enumeration + << XsdFacet::WhiteSpace + << XsdFacet::MaximumInclusive + << XsdFacet::MaximumExclusive + << XsdFacet::MinimumInclusive + << XsdFacet::MinimumExclusive + << XsdFacet::Assertion; + + m_allowedAtomicFacets.insert(BuiltinTypes::xsTime->name(m_namePool), facets); + } + + // date + { + QSet facets; + facets << XsdFacet::Pattern + << XsdFacet::Enumeration + << XsdFacet::WhiteSpace + << XsdFacet::MaximumInclusive + << XsdFacet::MaximumExclusive + << XsdFacet::MinimumInclusive + << XsdFacet::MinimumExclusive + << XsdFacet::Assertion; + + m_allowedAtomicFacets.insert(BuiltinTypes::xsDate->name(m_namePool), facets); + } + + // gYearMonth + { + QSet facets; + facets << XsdFacet::Pattern + << XsdFacet::Enumeration + << XsdFacet::WhiteSpace + << XsdFacet::MaximumInclusive + << XsdFacet::MaximumExclusive + << XsdFacet::MinimumInclusive + << XsdFacet::MinimumExclusive + << XsdFacet::Assertion; + + m_allowedAtomicFacets.insert(BuiltinTypes::xsGYearMonth->name(m_namePool), facets); + } + + // gYear + { + QSet facets; + facets << XsdFacet::Pattern + << XsdFacet::Enumeration + << XsdFacet::WhiteSpace + << XsdFacet::MaximumInclusive + << XsdFacet::MaximumExclusive + << XsdFacet::MinimumInclusive + << XsdFacet::MinimumExclusive + << XsdFacet::Assertion; + + m_allowedAtomicFacets.insert(BuiltinTypes::xsGYear->name(m_namePool), facets); + } + + // gMonthDay + { + QSet facets; + facets << XsdFacet::Pattern + << XsdFacet::Enumeration + << XsdFacet::WhiteSpace + << XsdFacet::MaximumInclusive + << XsdFacet::MaximumExclusive + << XsdFacet::MinimumInclusive + << XsdFacet::MinimumExclusive + << XsdFacet::Assertion; + + m_allowedAtomicFacets.insert(BuiltinTypes::xsGMonthDay->name(m_namePool), facets); + } + + // gDay + { + QSet facets; + facets << XsdFacet::Pattern + << XsdFacet::Enumeration + << XsdFacet::WhiteSpace + << XsdFacet::MaximumInclusive + << XsdFacet::MaximumExclusive + << XsdFacet::MinimumInclusive + << XsdFacet::MinimumExclusive + << XsdFacet::Assertion; + + m_allowedAtomicFacets.insert(BuiltinTypes::xsGDay->name(m_namePool), facets); + } + + // gMonth + { + QSet facets; + facets << XsdFacet::Pattern + << XsdFacet::Enumeration + << XsdFacet::WhiteSpace + << XsdFacet::MaximumInclusive + << XsdFacet::MaximumExclusive + << XsdFacet::MinimumInclusive + << XsdFacet::MinimumExclusive + << XsdFacet::Assertion; + + m_allowedAtomicFacets.insert(BuiltinTypes::xsGMonth->name(m_namePool), facets); + } + + // hexBinary + { + QSet facets; + facets << XsdFacet::Length + << XsdFacet::MinimumLength + << XsdFacet::MaximumLength + << XsdFacet::Pattern + << XsdFacet::Enumeration + << XsdFacet::WhiteSpace + << XsdFacet::Assertion; + + m_allowedAtomicFacets.insert(BuiltinTypes::xsHexBinary->name(m_namePool), facets); + } + + // base64Binary + { + QSet facets; + facets << XsdFacet::Length + << XsdFacet::MinimumLength + << XsdFacet::MaximumLength + << XsdFacet::Pattern + << XsdFacet::Enumeration + << XsdFacet::WhiteSpace + << XsdFacet::Assertion; + + m_allowedAtomicFacets.insert(BuiltinTypes::xsBase64Binary->name(m_namePool), facets); + } + + // anyURI + { + QSet facets; + facets << XsdFacet::Length + << XsdFacet::MinimumLength + << XsdFacet::MaximumLength + << XsdFacet::Pattern + << XsdFacet::Enumeration + << XsdFacet::WhiteSpace + << XsdFacet::Assertion; + + m_allowedAtomicFacets.insert(BuiltinTypes::xsAnyURI->name(m_namePool), facets); + } + + // QName + { + QSet facets; + facets << XsdFacet::Length + << XsdFacet::MinimumLength + << XsdFacet::MaximumLength + << XsdFacet::Pattern + << XsdFacet::Enumeration + << XsdFacet::WhiteSpace + << XsdFacet::Assertion; + + m_allowedAtomicFacets.insert(BuiltinTypes::xsQName->name(m_namePool), facets); + } + + // NOTATION + { + QSet facets; + facets << XsdFacet::Length + << XsdFacet::MinimumLength + << XsdFacet::MaximumLength + << XsdFacet::Pattern + << XsdFacet::Enumeration + << XsdFacet::WhiteSpace + << XsdFacet::Assertion; + + m_allowedAtomicFacets.insert(BuiltinTypes::xsNOTATION->name(m_namePool), facets); + } +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdschemacontext.cpp b/src/xmlpatterns/schema/qxsdschemacontext.cpp new file mode 100644 index 0000000..57736bd --- /dev/null +++ b/src/xmlpatterns/schema/qxsdschemacontext.cpp @@ -0,0 +1,498 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qxsdschemacontext_p.h" + +#include "qderivedinteger_p.h" +#include "qderivedstring_p.h" +#include "qxsdschematypesfactory_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +XsdSchemaContext::XsdSchemaContext(const NamePool::Ptr &namePool) + : m_namePool(namePool) + , m_networkAccessManager(0) + , m_uriResolver(0) + , m_messageHandler(0) +{ +} + +NamePool::Ptr XsdSchemaContext::namePool() const +{ + return m_namePool; +} + +QUrl XsdSchemaContext::baseURI() const +{ + return m_baseURI; +} + +void XsdSchemaContext::setBaseURI(const QUrl &uri) +{ + m_baseURI = uri; +} + +void XsdSchemaContext::setNetworkAccessManager(QNetworkAccessManager *accessManager) +{ + m_networkAccessManager = accessManager; +} + +QNetworkAccessManager* XsdSchemaContext::networkAccessManager() const +{ + return m_networkAccessManager; +} + +void XsdSchemaContext::setMessageHandler(QAbstractMessageHandler *handler) +{ + m_messageHandler = handler; +} + +QAbstractMessageHandler* XsdSchemaContext::messageHandler() const +{ + return m_messageHandler; +} + +QSourceLocation XsdSchemaContext::locationFor(const SourceLocationReflection *const) const +{ + return QSourceLocation(); +} + +void XsdSchemaContext::setUriResolver(QAbstractUriResolver *uriResolver) +{ + m_uriResolver = uriResolver; +} + +const QAbstractUriResolver* XsdSchemaContext::uriResolver() const +{ + return m_uriResolver; +} + +XsdFacet::Hash XsdSchemaContext::facetsForType(const AnySimpleType::Ptr &type) const +{ + if (type->isDefinedBySchema()) + return XsdSimpleType::Ptr(type)->facets(); + else { + if (m_builtinTypesFacetList.isEmpty()) + m_builtinTypesFacetList = setupBuiltinTypesFacetList(); + + return m_builtinTypesFacetList.value(type); + } +} + +SchemaTypeFactory::Ptr XsdSchemaContext::schemaTypeFactory() const +{ + if (!m_schemaTypeFactory) + m_schemaTypeFactory = SchemaTypeFactory::Ptr(new XsdSchemaTypesFactory(m_namePool)); + + return m_schemaTypeFactory; +} + +QHash XsdSchemaContext::setupBuiltinTypesFacetList() const +{ + QHash hash; + + const XsdFacet::Ptr fixedCollapseWhiteSpace(new XsdFacet()); + fixedCollapseWhiteSpace->setType(XsdFacet::WhiteSpace); + fixedCollapseWhiteSpace->setValue(DerivedString::fromLexical(m_namePool, XsdSchemaToken::toString(XsdSchemaToken::Collapse))); + fixedCollapseWhiteSpace->setFixed(true); + + const XsdFacet::Ptr collapseWhiteSpace(new XsdFacet()); + collapseWhiteSpace->setType(XsdFacet::WhiteSpace); + collapseWhiteSpace->setValue(DerivedString::fromLexical(m_namePool, XsdSchemaToken::toString(XsdSchemaToken::Collapse))); + collapseWhiteSpace->setFixed(false); + + const XsdFacet::Ptr preserveWhiteSpace(new XsdFacet()); + preserveWhiteSpace->setType(XsdFacet::WhiteSpace); + preserveWhiteSpace->setValue(DerivedString::fromLexical(m_namePool, XsdSchemaToken::toString(XsdSchemaToken::Preserve))); + preserveWhiteSpace->setFixed(false); + + const XsdFacet::Ptr replaceWhiteSpace(new XsdFacet()); + replaceWhiteSpace->setType(XsdFacet::WhiteSpace); + replaceWhiteSpace->setValue(DerivedString::fromLexical(m_namePool, XsdSchemaToken::toString(XsdSchemaToken::Replace))); + replaceWhiteSpace->setFixed(false); + + const XsdFacet::Ptr fixedZeroFractionDigits(new XsdFacet()); + fixedZeroFractionDigits->setType(XsdFacet::FractionDigits); + fixedZeroFractionDigits->setValue(DerivedInteger::fromValue(m_namePool, 0)); + fixedZeroFractionDigits->setFixed(true); + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsString]; + facets.insert(preserveWhiteSpace->type(), preserveWhiteSpace); + } + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsBoolean]; + facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace); + } + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsDecimal]; + facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace); + } + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsFloat]; + facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace); + } + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsDouble]; + facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace); + } + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsDuration]; + facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace); + } + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsDateTime]; + facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace); + } + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsTime]; + facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace); + } + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsDate]; + facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace); + } + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsGYearMonth]; + facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace); + } + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsGYear]; + facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace); + } + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsGMonthDay]; + facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace); + } + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsGDay]; + facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace); + } + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsGMonth]; + facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace); + } + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsHexBinary]; + facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace); + } + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsBase64Binary]; + facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace); + } + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsAnyURI]; + facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace); + } + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsQName]; + facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace); + } + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsNOTATION]; + facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace); + } + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsNormalizedString]; + facets.insert(replaceWhiteSpace->type(), replaceWhiteSpace); + } + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsToken]; + facets.insert(collapseWhiteSpace->type(), collapseWhiteSpace); + } + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsLanguage]; + facets.insert(collapseWhiteSpace->type(), collapseWhiteSpace); + + const XsdFacet::Ptr pattern(new XsdFacet()); + pattern->setType(XsdFacet::Pattern); + pattern->setMultiValue(AtomicValue::List() << DerivedString::fromLexical(m_namePool, QString::fromLatin1("[a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*"))); + facets.insert(pattern->type(), pattern); + } + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsNMTOKEN]; + facets.insert(collapseWhiteSpace->type(), collapseWhiteSpace); + + const XsdFacet::Ptr pattern(new XsdFacet()); + pattern->setType(XsdFacet::Pattern); + pattern->setMultiValue(AtomicValue::List() << DerivedString::fromLexical(m_namePool, QString::fromLatin1("\\c+"))); + facets.insert(pattern->type(), pattern); + } + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsName]; + facets.insert(collapseWhiteSpace->type(), collapseWhiteSpace); + + const XsdFacet::Ptr pattern(new XsdFacet()); + pattern->setType(XsdFacet::Pattern); + pattern->setMultiValue(AtomicValue::List() << DerivedString::fromLexical(m_namePool, QString::fromLatin1("\\i\\c*"))); + facets.insert(pattern->type(), pattern); + } + + const XsdFacet::Ptr ncNamePattern(new XsdFacet()); + { + ncNamePattern->setType(XsdFacet::Pattern); + AtomicValue::List patterns; + patterns << DerivedString::fromLexical(m_namePool, QString::fromLatin1("\\i\\c*")); + patterns << DerivedString::fromLexical(m_namePool, QString::fromLatin1("[\\i-[:]][\\c-[:]]*")); + ncNamePattern->setMultiValue(patterns); + } + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsNCName]; + facets.insert(collapseWhiteSpace->type(), collapseWhiteSpace); + facets.insert(ncNamePattern->type(), ncNamePattern); + } + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsID]; + facets.insert(collapseWhiteSpace->type(), collapseWhiteSpace); + facets.insert(ncNamePattern->type(), ncNamePattern); + } + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsIDREF]; + facets.insert(collapseWhiteSpace->type(), collapseWhiteSpace); + facets.insert(ncNamePattern->type(), ncNamePattern); + } + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsENTITY]; + facets.insert(collapseWhiteSpace->type(), collapseWhiteSpace); + facets.insert(ncNamePattern->type(), ncNamePattern); + } + + const XsdFacet::Ptr integerPattern(new XsdFacet()); + integerPattern->setType(XsdFacet::Pattern); + integerPattern->setMultiValue(AtomicValue::List() << DerivedString::fromLexical(m_namePool, QString::fromLatin1("[\\-+]?[0-9]+"))); + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsInteger]; + facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace); + facets.insert(fixedZeroFractionDigits->type(), fixedZeroFractionDigits); + facets.insert(integerPattern->type(), integerPattern); + } + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsNonPositiveInteger]; + facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace); + facets.insert(fixedZeroFractionDigits->type(), fixedZeroFractionDigits); + facets.insert(integerPattern->type(), integerPattern); + + const XsdFacet::Ptr maxInclusive(new XsdFacet()); + maxInclusive->setType(XsdFacet::MaximumInclusive); + maxInclusive->setValue(DerivedString::fromLexical(m_namePool, QString::fromLatin1("0"))); + facets.insert(maxInclusive->type(), maxInclusive); + } + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsNegativeInteger]; + facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace); + facets.insert(fixedZeroFractionDigits->type(), fixedZeroFractionDigits); + facets.insert(integerPattern->type(), integerPattern); + + const XsdFacet::Ptr maxInclusive(new XsdFacet()); + maxInclusive->setType(XsdFacet::MaximumInclusive); + maxInclusive->setValue(DerivedString::fromLexical(m_namePool, QString::fromLatin1("-1"))); + facets.insert(maxInclusive->type(), maxInclusive); + } + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsLong]; + facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace); + facets.insert(fixedZeroFractionDigits->type(), fixedZeroFractionDigits); + facets.insert(integerPattern->type(), integerPattern); + + const XsdFacet::Ptr maxInclusive(new XsdFacet()); + maxInclusive->setType(XsdFacet::MaximumInclusive); + maxInclusive->setValue(DerivedString::fromLexical(m_namePool, QString::fromLatin1("9223372036854775807"))); + facets.insert(maxInclusive->type(), maxInclusive); + + const XsdFacet::Ptr minInclusive(new XsdFacet()); + minInclusive->setType(XsdFacet::MinimumInclusive); + minInclusive->setValue(DerivedString::fromLexical(m_namePool, QString::fromLatin1("-9223372036854775808"))); + facets.insert(minInclusive->type(), minInclusive); + } + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsInt]; + facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace); + facets.insert(fixedZeroFractionDigits->type(), fixedZeroFractionDigits); + facets.insert(integerPattern->type(), integerPattern); + + const XsdFacet::Ptr maxInclusive(new XsdFacet()); + maxInclusive->setType(XsdFacet::MaximumInclusive); + maxInclusive->setValue(DerivedString::fromLexical(m_namePool, QString::fromLatin1("2147483647"))); + facets.insert(maxInclusive->type(), maxInclusive); + + const XsdFacet::Ptr minInclusive(new XsdFacet()); + minInclusive->setType(XsdFacet::MinimumInclusive); + minInclusive->setValue(DerivedString::fromLexical(m_namePool, QString::fromLatin1("-2147483648"))); + facets.insert(minInclusive->type(), minInclusive); + } + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsShort]; + facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace); + facets.insert(fixedZeroFractionDigits->type(), fixedZeroFractionDigits); + facets.insert(integerPattern->type(), integerPattern); + + const XsdFacet::Ptr maxInclusive(new XsdFacet()); + maxInclusive->setType(XsdFacet::MaximumInclusive); + maxInclusive->setValue(DerivedString::fromLexical(m_namePool, QString::fromLatin1("32767"))); + facets.insert(maxInclusive->type(), maxInclusive); + + const XsdFacet::Ptr minInclusive(new XsdFacet()); + minInclusive->setType(XsdFacet::MinimumInclusive); + minInclusive->setValue(DerivedString::fromLexical(m_namePool, QString::fromLatin1("-32768"))); + facets.insert(minInclusive->type(), minInclusive); + } + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsByte]; + facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace); + facets.insert(fixedZeroFractionDigits->type(), fixedZeroFractionDigits); + facets.insert(integerPattern->type(), integerPattern); + + const XsdFacet::Ptr maxInclusive(new XsdFacet()); + maxInclusive->setType(XsdFacet::MaximumInclusive); + maxInclusive->setValue(DerivedString::fromLexical(m_namePool, QString::fromLatin1("127"))); + facets.insert(maxInclusive->type(), maxInclusive); + + const XsdFacet::Ptr minInclusive(new XsdFacet()); + minInclusive->setType(XsdFacet::MinimumInclusive); + minInclusive->setValue(DerivedString::fromLexical(m_namePool, QString::fromLatin1("-128"))); + facets.insert(minInclusive->type(), minInclusive); + } + + const XsdFacet::Ptr unsignedMinInclusive(new XsdFacet()); + unsignedMinInclusive->setType(XsdFacet::MinimumInclusive); + unsignedMinInclusive->setValue(DerivedString::fromLexical(m_namePool, QString::fromLatin1("0"))); + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsNonNegativeInteger]; + facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace); + facets.insert(fixedZeroFractionDigits->type(), fixedZeroFractionDigits); + facets.insert(integerPattern->type(), integerPattern); + facets.insert(unsignedMinInclusive->type(), unsignedMinInclusive); + } + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsUnsignedLong]; + facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace); + facets.insert(fixedZeroFractionDigits->type(), fixedZeroFractionDigits); + facets.insert(integerPattern->type(), integerPattern); + facets.insert(unsignedMinInclusive->type(), unsignedMinInclusive); + + const XsdFacet::Ptr maxInclusive(new XsdFacet()); + maxInclusive->setType(XsdFacet::MaximumInclusive); + maxInclusive->setValue(DerivedString::fromLexical(m_namePool, QString::fromLatin1("18446744073709551615"))); + facets.insert(maxInclusive->type(), maxInclusive); + } + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsUnsignedInt]; + facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace); + facets.insert(fixedZeroFractionDigits->type(), fixedZeroFractionDigits); + facets.insert(integerPattern->type(), integerPattern); + facets.insert(unsignedMinInclusive->type(), unsignedMinInclusive); + + const XsdFacet::Ptr maxInclusive(new XsdFacet()); + maxInclusive->setType(XsdFacet::MaximumInclusive); + maxInclusive->setValue(DerivedString::fromLexical(m_namePool, QString::fromLatin1("4294967295"))); + facets.insert(maxInclusive->type(), maxInclusive); + } + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsUnsignedShort]; + facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace); + facets.insert(fixedZeroFractionDigits->type(), fixedZeroFractionDigits); + facets.insert(integerPattern->type(), integerPattern); + facets.insert(unsignedMinInclusive->type(), unsignedMinInclusive); + + const XsdFacet::Ptr maxInclusive(new XsdFacet()); + maxInclusive->setType(XsdFacet::MaximumInclusive); + maxInclusive->setValue(DerivedString::fromLexical(m_namePool, QString::fromLatin1("65535"))); + facets.insert(maxInclusive->type(), maxInclusive); + } + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsUnsignedByte]; + facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace); + facets.insert(fixedZeroFractionDigits->type(), fixedZeroFractionDigits); + facets.insert(integerPattern->type(), integerPattern); + facets.insert(unsignedMinInclusive->type(), unsignedMinInclusive); + + const XsdFacet::Ptr maxInclusive(new XsdFacet()); + maxInclusive->setType(XsdFacet::MaximumInclusive); + maxInclusive->setValue(DerivedString::fromLexical(m_namePool, QString::fromLatin1("255"))); + facets.insert(maxInclusive->type(), maxInclusive); + } + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsPositiveInteger]; + facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace); + facets.insert(fixedZeroFractionDigits->type(), fixedZeroFractionDigits); + + const XsdFacet::Ptr minInclusive(new XsdFacet()); + minInclusive->setType(XsdFacet::MinimumInclusive); + minInclusive->setValue(DerivedString::fromLexical(m_namePool, QString::fromLatin1("1"))); + facets.insert(minInclusive->type(), minInclusive); + } + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsYearMonthDuration]; + facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace); + + const XsdFacet::Ptr pattern(new XsdFacet()); + pattern->setType(XsdFacet::Pattern); + pattern->setMultiValue(AtomicValue::List() << DerivedString::fromLexical(m_namePool, QString::fromLatin1("[^DT]*"))); + facets.insert(pattern->type(), pattern); + } + + { + XsdFacet::Hash &facets = hash[BuiltinTypes::xsDayTimeDuration]; + facets.insert(fixedCollapseWhiteSpace->type(), fixedCollapseWhiteSpace); + + const XsdFacet::Ptr pattern(new XsdFacet()); + pattern->setType(XsdFacet::Pattern); + pattern->setMultiValue(AtomicValue::List() << DerivedString::fromLexical(m_namePool, QString::fromLatin1("[^YM]*(T.*)?"))); + facets.insert(pattern->type(), pattern); + } + + return hash; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdschemacontext_p.h b/src/xmlpatterns/schema/qxsdschemacontext_p.h new file mode 100644 index 0000000..cf52028 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdschemacontext_p.h @@ -0,0 +1,157 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdSchemaContext_H +#define Patternist_XsdSchemaContext_H + +#include "qnamedschemacomponent_p.h" +#include "qreportcontext_p.h" +#include "qschematypefactory_p.h" +#include "qxsdschematoken_p.h" +#include "qxsdschema_p.h" +#include "qxsdschemachecker_p.h" +#include "qxsdschemaresolver_p.h" + +#include +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short A context for schema parsing and validation. + * + * This class provides the infrastructure for error reporting and + * network access. Additionally it stores objects that are used by + * both, the parser and the validator. + * + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdSchemaContext : public ReportContext + { + public: + /** + * A smart pointer wrapping XsdSchemaContext instances. + */ + typedef QExplicitlySharedDataPointer Ptr; + + /** + * Creates a new schema context object. + * + * @param namePool The name pool all names belong to. + */ + XsdSchemaContext(const NamePool::Ptr &namePool); + + /** + * Returns the name pool of the schema context. + */ + virtual NamePool::Ptr namePool() const; + + /** + * Sets the base URI for the main schema. + * + * The main schema is the one that includes resp. imports + * all the other schema files. + */ + virtual void setBaseURI(const QUrl &uri); + + /** + * Returns the base URI of the main schema. + */ + virtual QUrl baseURI() const; + + /** + * Sets the network access manager that should be used + * to access referenced schema definitions. + */ + void setNetworkAccessManager(QNetworkAccessManager *accessManager); + + /** + * Returns the network access manager that is used to + * access referenced schema definitions. + */ + virtual QNetworkAccessManager* networkAccessManager() const; + + /** + * Sets the message @p handler used by the context for error reporting. + */ + void setMessageHandler(QAbstractMessageHandler *handler); + + /** + * Returns the message handler used by the context for + * error reporting. + */ + virtual QAbstractMessageHandler* messageHandler() const; + + /** + * Always returns an empty source location. + */ + virtual QSourceLocation locationFor(const SourceLocationReflection *const reflection) const; + + /** + * Sets the uri @p resolver that is used for resolving URIs in the + * schema parser. + */ + void setUriResolver(QAbstractUriResolver *resolver); + + /** + * Returns the uri resolver that is used for resolving URIs in the + * schema parser. + */ + virtual const QAbstractUriResolver* uriResolver() const; + + /** + * Returns the list of facets for the given simple @p type. + */ + XsdFacet::Hash facetsForType(const AnySimpleType::Ptr &type) const; + + /** + * Returns a schema type factory that contains some predefined schema types. + */ + SchemaTypeFactory::Ptr schemaTypeFactory() const; + + /** + * The following variables should not be accessed directly. + */ + mutable SchemaTypeFactory::Ptr m_schemaTypeFactory; + mutable QHash m_builtinTypesFacetList; + + private: + QHash setupBuiltinTypesFacetList() const; + + NamePool::Ptr m_namePool; + QNetworkAccessManager* m_networkAccessManager; + QUrl m_baseURI; + QAbstractUriResolver* m_uriResolver; + QAbstractMessageHandler* m_messageHandler; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsdschemadebugger.cpp b/src/xmlpatterns/schema/qxsdschemadebugger.cpp new file mode 100644 index 0000000..850192c --- /dev/null +++ b/src/xmlpatterns/schema/qxsdschemadebugger.cpp @@ -0,0 +1,196 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qxsdschemadebugger_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +XsdSchemaDebugger::XsdSchemaDebugger(const NamePool::Ptr &namePool) + : m_namePool(namePool) +{ +} + +void XsdSchemaDebugger::dumpParticle(const XsdParticle::Ptr &particle, int level) +{ + QString prefix; prefix.fill(QLatin1Char(' '), level); + + qDebug("%s min=%s max=%s", qPrintable(prefix), qPrintable(QString::number(particle->minimumOccurs())), + qPrintable(particle->maximumOccursUnbounded() ? QLatin1String("unbounded") : QString::number(particle->maximumOccurs()))); + + if (particle->term()->isElement()) { + qDebug("%selement (%s)", qPrintable(prefix), qPrintable(XsdElement::Ptr(particle->term())->displayName(m_namePool))); + } else if (particle->term()->isModelGroup()) { + const XsdModelGroup::Ptr group(particle->term()); + if (group->compositor() == XsdModelGroup::SequenceCompositor) { + qDebug("%ssequence", qPrintable(prefix)); + } else if (group->compositor() == XsdModelGroup::AllCompositor) { + qDebug("%sall", qPrintable(prefix)); + } else if (group->compositor() == XsdModelGroup::ChoiceCompositor) { + qDebug("%schoice", qPrintable(prefix)); + } + + for (int i = 0; i < group->particles().count(); ++i) + dumpParticle(group->particles().at(i), level + 5); + } else if (particle->term()->isWildcard()) { + XsdWildcard::Ptr wildcard(particle->term()); + qDebug("%swildcard (process=%d)", qPrintable(prefix), wildcard->processContents()); + } +} + +void XsdSchemaDebugger::dumpInheritance(const SchemaType::Ptr &type, int level) +{ + QString prefix; prefix.fill(QLatin1Char(' '), level); + qDebug("%s-->%s", qPrintable(prefix), qPrintable(type->displayName(m_namePool))); + if (type->wxsSuperType()) + dumpInheritance(type->wxsSuperType(), ++level); +} + +void XsdSchemaDebugger::dumpWildcard(const XsdWildcard::Ptr &wildcard) +{ + QVector varietyNames; + varietyNames.append(QLatin1String("Any")); + varietyNames.append(QLatin1String("Enumeration")); + varietyNames.append(QLatin1String("Not")); + + QVector processContentsNames; + processContentsNames.append(QLatin1String("Strict")); + processContentsNames.append(QLatin1String("Lax")); + processContentsNames.append(QLatin1String("Skip")); + + qDebug(" processContents: %s", qPrintable(processContentsNames.at((int)wildcard->processContents()))); + const XsdWildcard::NamespaceConstraint::Ptr constraint = wildcard->namespaceConstraint(); + qDebug(" variety: %s", qPrintable(varietyNames.at((int)constraint->variety()))); + if (constraint->variety() != XsdWildcard::NamespaceConstraint::Any) + qDebug() << " namespaces:" << constraint->namespaces(); +} + +void XsdSchemaDebugger::dumpType(const SchemaType::Ptr &type) +{ + if (type->isComplexType()) { + const XsdComplexType::Ptr complexType(type); + qDebug("\n+++ Complex Type +++"); + qDebug("Name: %s (abstract: %s)", qPrintable(complexType->displayName(m_namePool)), complexType->isAbstract() ? "yes" : "no"); + if (complexType->wxsSuperType()) + qDebug(" base type: %s", qPrintable(complexType->wxsSuperType()->displayName(m_namePool))); + else + qDebug(" base type: (none)"); + if (complexType->contentType()->variety() == XsdComplexType::ContentType::Empty) + qDebug(" content type: empty"); + if (complexType->contentType()->variety() == XsdComplexType::ContentType::Simple) + qDebug(" content type: simple"); + if (complexType->contentType()->variety() == XsdComplexType::ContentType::ElementOnly) + qDebug(" content type: element-only"); + if (complexType->contentType()->variety() == XsdComplexType::ContentType::Mixed) + qDebug(" content type: mixed"); + if (complexType->contentType()->variety() == XsdComplexType::ContentType::Simple) { + if (complexType->contentType()->simpleType()) + qDebug(" simple type: %s", qPrintable(complexType->contentType()->simpleType()->displayName(m_namePool))); + else + qDebug(" simple type: (none)"); + } + + const XsdAttributeUse::List uses = complexType->attributeUses(); + qDebug(" %d attributes", uses.count()); + for (int i = 0; i < uses.count(); ++i) { + qDebug(" attr: %s", qPrintable(uses.at(i)->attribute()->displayName(m_namePool))); + } + qDebug(" has attribute wildcard: %s", complexType->attributeWildcard() ? "yes" : "no"); + if (complexType->attributeWildcard()) { + dumpWildcard(complexType->attributeWildcard()); + } + + if (complexType->contentType()->particle()) { + dumpParticle(complexType->contentType()->particle(), 5); + } + } else { + qDebug("\n+++ Simple Type +++"); + qDebug("Name: %s", qPrintable(type->displayName(m_namePool))); + if (type->isDefinedBySchema()) { + const XsdSimpleType::Ptr simpleType(type); + if (simpleType->primitiveType()) + qDebug(" primitive type: %s", qPrintable(simpleType->primitiveType()->displayName(m_namePool))); + else + qDebug(" primitive type: (none)"); + } + dumpInheritance(type, 0); + } +} + + +void XsdSchemaDebugger::dumpElement(const XsdElement::Ptr &element) +{ + QStringList disallowedSubstGroup; + if (element->disallowedSubstitutions() & XsdElement::RestrictionConstraint) + disallowedSubstGroup << QLatin1String("restriction"); + if (element->disallowedSubstitutions() & XsdElement::ExtensionConstraint) + disallowedSubstGroup << QLatin1String("extension"); + if (element->disallowedSubstitutions() & XsdElement::SubstitutionConstraint) + disallowedSubstGroup << QLatin1String("substitution"); + + + qDebug() << "Name:" << element->displayName(m_namePool); + qDebug() << "IsAbstract:" << (element->isAbstract() ? "yes" : "no"); + qDebug() << "Type:" << element->type()->displayName(m_namePool); + qDebug() << "DisallowedSubstitutionGroups:" << disallowedSubstGroup.join(QLatin1String("' ")); +} + +void XsdSchemaDebugger::dumpAttribute(const XsdAttribute::Ptr &attribute) +{ + qDebug() << "Name:" << attribute->displayName(m_namePool); + qDebug() << "Type:" << attribute->type()->displayName(m_namePool); +} + +void XsdSchemaDebugger::dumpSchema(const XsdSchema::Ptr &schema) +{ + qDebug() << "------------------------------ Schema -------------------------------"; + + // elements + { + qDebug() << "Global Elements:"; + const XsdElement::List elements = schema->elements(); + for (int i = 0; i < elements.count(); ++i) { + dumpElement(elements.at(i)); + } + } + + // attributes + { + qDebug() << "Global Attributes:"; + const XsdAttribute::List attributes = schema->attributes(); + for (int i = 0; i < attributes.count(); ++i) { + dumpAttribute(attributes.at(i)); + } + } + + // types + { + qDebug() << "Global Types:"; + const SchemaType::List types = schema->types(); + for (int i = 0; i < types.count(); ++i) { + dumpType(types.at(i)); + } + } + + // anonymous types + { + qDebug() << "Anonymous Types:"; + const SchemaType::List types = schema->anonymousTypes(); + for (int i = 0; i < types.count(); ++i) { + dumpType(types.at(i)); + } + } + + qDebug() << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdschemadebugger_p.h b/src/xmlpatterns/schema/qxsdschemadebugger_p.h new file mode 100644 index 0000000..8c12f0f --- /dev/null +++ b/src/xmlpatterns/schema/qxsdschemadebugger_p.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdSchemaDebugger_H +#define Patternist_XsdSchemaDebugger_H + +#include "qxsdschema_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * A helper class to print out the structure of a compiled schema. + */ + class XsdSchemaDebugger + { + public: + /** + * Creates a new schema debugger. + * + * @param namePool The name pool that the schema uses. + */ + XsdSchemaDebugger(const NamePool::Ptr &namePool); + + /** + * Dumps the structure of the given @p particle. + * + * @param particle The particle to dump. + * @param level The level of indention. + */ + void dumpParticle(const XsdParticle::Ptr &particle, int level = 0); + + /** + * Dumps the inheritance path of the given @p type. + * + * @param type The type to dump. + * @param level The level of indention. + */ + void dumpInheritance(const SchemaType::Ptr &type, int level = 0); + + /** + * Dumps the structure of the given @p wildcard. + */ + void dumpWildcard(const XsdWildcard::Ptr &wildcard); + + /** + * Dumps the structure of the given @p type. + */ + void dumpType(const SchemaType::Ptr &type); + + /** + * Dumps the structure of the given @p element. + */ + void dumpElement(const XsdElement::Ptr &element); + + /** + * Dumps the structure of the given @p attribute. + */ + void dumpAttribute(const XsdAttribute::Ptr &attribute); + + /** + * Dumps the structure of the complete @p schema. + */ + void dumpSchema(const XsdSchema::Ptr &schema); + + private: + NamePool::Ptr m_namePool; + }; + +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsdschemahelper.cpp b/src/xmlpatterns/schema/qxsdschemahelper.cpp new file mode 100644 index 0000000..752af89 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdschemahelper.cpp @@ -0,0 +1,791 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qxsdschemahelper_p.h" + +#include "qbuiltintypes_p.h" +#include "qvaluefactory_p.h" +#include "qxsdcomplextype_p.h" +#include "qxsdmodelgroup_p.h" +#include "qxsdsimpletype_p.h" +#include "qxsdtypechecker_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +/* + * Calculates the effective total range minimum of the given @p particle as + * described by the algorithm in the schema spec. + */ +static inline unsigned int effectiveTotalRangeMinimum(const XsdParticle::Ptr &particle) +{ + const XsdModelGroup::Ptr group = particle->term(); + + if (group->compositor() == XsdModelGroup::ChoiceCompositor) { + // @see http://www.w3.org/TR/xmlschema11-1/# cos-choice-range + + int minValue = -1; + + const XsdParticle::List particles = group->particles(); + if (particles.isEmpty()) + minValue = 0; + + for (int i = 0; i < particles.count(); ++i) { + const XsdParticle::Ptr particle = particles.at(i); + + if (particle->term()->isElement() || particle->term()->isWildcard()) { + if (minValue == -1) { + minValue = particle->minimumOccurs(); + } else { + minValue = qMin((unsigned int)minValue, particle->minimumOccurs()); + } + } else if (particle->term()->isModelGroup()) { + if (minValue == -1) { + minValue = effectiveTotalRangeMinimum(particle); + } else { + minValue = qMin((unsigned int)minValue, effectiveTotalRangeMinimum(particle)); + } + } + } + + return (particle->minimumOccurs() * minValue); + + } else { + // @see http://www.w3.org/TR/xmlschema11-1/# cos-seq-range + + unsigned int sum = 0; + const XsdParticle::List particles = group->particles(); + for (int i = 0; i < particles.count(); ++i) { + const XsdParticle::Ptr particle = particles.at(i); + + if (particle->term()->isElement() || particle->term()->isWildcard()) + sum += particle->minimumOccurs(); + else if (particle->term()->isModelGroup()) + sum += effectiveTotalRangeMinimum(particle); + } + + return (particle->minimumOccurs() * sum); + } +} + +bool XsdSchemaHelper::isParticleEmptiable(const XsdParticle::Ptr &particle) +{ + // @see http://www.w3.org/TR/xmlschema11-1/#cos-group-emptiable + + if (particle->minimumOccurs() == 0) + return true; + + if (!(particle->term()->isModelGroup())) + return false; + + return (effectiveTotalRangeMinimum(particle) == 0); +} + +bool XsdSchemaHelper::wildcardAllowsNamespaceName(const QString &nameSpace, const XsdWildcard::NamespaceConstraint::Ptr &constraint) +{ + // @see http://www.w3.org/TR/xmlschema11-1/#cvc-wildcard-namespace + + // 1 + if (constraint->variety() == XsdWildcard::NamespaceConstraint::Any) + return true; + + // 2 + if (constraint->variety() == XsdWildcard::NamespaceConstraint::Not) { // 2.1 + if (!constraint->namespaces().contains(nameSpace)) // 2.2 + if (nameSpace != XsdWildcard::absentNamespace()) // 2.3 + return true; + } + + // 3 + if (constraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration) { + if (constraint->namespaces().contains(nameSpace)) + return true; + } + + return false; +} + +bool XsdSchemaHelper::wildcardAllowsExpandedName(const QXmlName &name, const XsdWildcard::Ptr &wildcard, const NamePool::Ptr &namePool) +{ + // @see http://www.w3.org/TR/xmlschema11-1/#cvc-wildcard-name + + // 1 + if (!wildcardAllowsNamespaceName(namePool->stringForNamespace(name.namespaceURI()), wildcard->namespaceConstraint())) + return false; + + // 2, 3, 4 + //TODO: we have no disallowed namespace yet + + return true; +} + +// small helper function that should be available in Qt 4.6 +template +static inline bool containsSet(const QSet &super, const QSet &sub) +{ + QSetIterator it(sub); + while (it.hasNext()) { + if (!super.contains(it.next())) + return false; + } + + return true; +} + +bool XsdSchemaHelper::isWildcardSubset(const XsdWildcard::Ptr &wildcard, const XsdWildcard::Ptr &otherWildcard) +{ + // @see http://www.w3.org/TR/xmlschema11-1/#cos-ns-subset + // wildcard =^ sub + // otherWildcard =^ super + + const XsdWildcard::NamespaceConstraint::Ptr constraint(wildcard->namespaceConstraint()); + const XsdWildcard::NamespaceConstraint::Ptr otherConstraint(otherWildcard->namespaceConstraint()); + + // 1 + if (otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Any) + return true; + + // 2 + if ((constraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration) && (otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration)) { + if (containsSet(otherConstraint->namespaces(), constraint->namespaces())) + return true; + } + + // 3 + if ((constraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration) && (otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Not)) { + if (constraint->namespaces().intersect(otherConstraint->namespaces()).isEmpty()) + return true; + } + + // 4 + if ((constraint->variety() == XsdWildcard::NamespaceConstraint::Not) && (otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Not)) { + if (containsSet(constraint->namespaces(), otherConstraint->namespaces())) + return true; + } + + return false; +} + +XsdWildcard::Ptr XsdSchemaHelper::wildcardUnion(const XsdWildcard::Ptr &wildcard, const XsdWildcard::Ptr &otherWildcard) +{ + // @see http://www.w3.org/TR/xmlschema11-1/#cos-aw-union + + XsdWildcard::Ptr unionWildcard(new XsdWildcard()); + + const XsdWildcard::NamespaceConstraint::Ptr constraint(wildcard->namespaceConstraint()); + const XsdWildcard::NamespaceConstraint::Ptr otherConstraint(otherWildcard->namespaceConstraint()); + + // 1 + if ((constraint->variety() == otherConstraint->variety()) && + (constraint->namespaces() == otherConstraint->namespaces())) { + unionWildcard->namespaceConstraint()->setVariety(constraint->variety()); + unionWildcard->namespaceConstraint()->setNamespaces(constraint->namespaces()); + return unionWildcard; + } + + // 2 + if ((constraint->variety() == XsdWildcard::NamespaceConstraint::Any) || (otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Any)) { + unionWildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Any); + return unionWildcard; + } + + // 3 + if ((constraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration) && (otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration)) { + unionWildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Enumeration); + unionWildcard->namespaceConstraint()->setNamespaces(constraint->namespaces() + otherConstraint->namespaces()); + return unionWildcard; + } + + // 4 + if ((constraint->variety() == XsdWildcard::NamespaceConstraint::Not) && (otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Not)) { + if (constraint->namespaces() != otherConstraint->namespaces()) { + unionWildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Not); + unionWildcard->namespaceConstraint()->setNamespaces(QSet() << XsdWildcard::absentNamespace()); + return unionWildcard; + } + } + + // 5 + QSet sSet, negatedSet; + bool matches5 = false; + if (((constraint->variety() == XsdWildcard::NamespaceConstraint::Not) && !constraint->namespaces().contains(XsdWildcard::absentNamespace())) + && (otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration)) { + + negatedSet = constraint->namespaces(); + sSet = otherConstraint->namespaces(); + matches5 = true; + } else if (((otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Not) && !otherConstraint->namespaces().contains(XsdWildcard::absentNamespace())) + && (constraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration)) { + + negatedSet = otherConstraint->namespaces(); + sSet = constraint->namespaces(); + matches5 = true; + } + + if (matches5) { + if (sSet.contains(negatedSet.values().first()) && sSet.contains(XsdWildcard::absentNamespace())) { // 5.1 + unionWildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Any); + return unionWildcard; + } + if (sSet.contains(negatedSet.values().first()) && !sSet.contains(XsdWildcard::absentNamespace())) { // 5.2 + unionWildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Not); + unionWildcard->namespaceConstraint()->setNamespaces(QSet() << XsdWildcard::absentNamespace()); + return unionWildcard; + } + if (!sSet.contains(negatedSet.values().first()) && sSet.contains(XsdWildcard::absentNamespace())) { // 5.3 + return XsdWildcard::Ptr(); // not expressible + } + if (!sSet.contains(negatedSet.values().first()) && !sSet.contains(XsdWildcard::absentNamespace())) { // 5.4 + unionWildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Not); + unionWildcard->namespaceConstraint()->setNamespaces(negatedSet); + return unionWildcard; + } + } + + // 6 + bool matches6 = false; + if (((constraint->variety() == XsdWildcard::NamespaceConstraint::Not) && constraint->namespaces().contains(XsdWildcard::absentNamespace())) + && (otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration)) { + + negatedSet = constraint->namespaces(); + sSet = otherConstraint->namespaces(); + matches6 = true; + } else if (((otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Not) && otherConstraint->namespaces().contains(XsdWildcard::absentNamespace())) + && (constraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration)) { + + negatedSet = otherConstraint->namespaces(); + sSet = constraint->namespaces(); + matches6 = true; + } + + if (matches6) { + if (sSet.contains(XsdWildcard::absentNamespace())) { // 6.1 + unionWildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Any); + return unionWildcard; + } + if (!sSet.contains(XsdWildcard::absentNamespace())) { // 6.2 + unionWildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Not); + unionWildcard->namespaceConstraint()->setNamespaces(QSet() += XsdWildcard::absentNamespace()); + return unionWildcard; + } + } + + return XsdWildcard::Ptr(); +} + +XsdWildcard::Ptr XsdSchemaHelper::wildcardIntersection(const XsdWildcard::Ptr &wildcard, const XsdWildcard::Ptr &otherWildcard) +{ + // @see http://www.w3.org/TR/xmlschema11-1/#cos-aw-intersect + + const XsdWildcard::NamespaceConstraint::Ptr constraint(wildcard->namespaceConstraint()); + const XsdWildcard::NamespaceConstraint::Ptr otherConstraint(otherWildcard->namespaceConstraint()); + + const XsdWildcard::Ptr intersectionWildcard(new XsdWildcard()); + + // 1 + if ((constraint->variety() == otherConstraint->variety()) && + (constraint->namespaces() == otherConstraint->namespaces())) { + intersectionWildcard->namespaceConstraint()->setVariety(constraint->variety()); + intersectionWildcard->namespaceConstraint()->setNamespaces(constraint->namespaces()); + return intersectionWildcard; + } + + // 2 + if ((constraint->variety() == XsdWildcard::NamespaceConstraint::Any) && + (otherConstraint->variety() != XsdWildcard::NamespaceConstraint::Any)) { + intersectionWildcard->namespaceConstraint()->setVariety(otherConstraint->variety()); + intersectionWildcard->namespaceConstraint()->setNamespaces(otherConstraint->namespaces()); + return intersectionWildcard; + } + + // 2 + if ((constraint->variety() != XsdWildcard::NamespaceConstraint::Any) && + (otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Any)) { + intersectionWildcard->namespaceConstraint()->setVariety(constraint->variety()); + intersectionWildcard->namespaceConstraint()->setNamespaces(constraint->namespaces()); + return intersectionWildcard; + } + + // 3 + if ((constraint->variety() == XsdWildcard::NamespaceConstraint::Not) && + (otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration)) { + + QSet set = otherConstraint->namespaces(); + set.subtract(constraint->namespaces()); + set.remove(XsdWildcard::absentNamespace()); + + intersectionWildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Enumeration); + intersectionWildcard->namespaceConstraint()->setNamespaces(set); + + return intersectionWildcard; + } + + // 3 + if ((otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Not) && + (constraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration)) { + + QSet set = constraint->namespaces(); + set.subtract(otherConstraint->namespaces()); + set.remove(XsdWildcard::absentNamespace()); + + intersectionWildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Enumeration); + intersectionWildcard->namespaceConstraint()->setNamespaces(set); + + return intersectionWildcard; + } + + // 4 + if ((constraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration) && + (otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Enumeration)) { + + QSet set = constraint->namespaces(); + set.intersect(otherConstraint->namespaces()); + + intersectionWildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Enumeration); + intersectionWildcard->namespaceConstraint()->setNamespaces(set); + + return intersectionWildcard; + } + + // 6 + if ((constraint->variety() == XsdWildcard::NamespaceConstraint::Not) && + (otherConstraint->variety() == XsdWildcard::NamespaceConstraint::Not)) { + if (!(constraint->namespaces().contains(XsdWildcard::absentNamespace())) && otherConstraint->namespaces().contains(XsdWildcard::absentNamespace())) { + return wildcard; + } + if (constraint->namespaces().contains(XsdWildcard::absentNamespace()) && !(otherConstraint->namespaces().contains(XsdWildcard::absentNamespace()))) { + return otherWildcard; + } + } + + // 5 as not expressible return empty wildcard + return XsdWildcard::Ptr(); +} + +static SchemaType::DerivationConstraints convertBlockingConstraints(const NamedSchemaComponent::BlockingConstraints &constraints) +{ + SchemaType::DerivationConstraints result = 0; + + if (constraints & NamedSchemaComponent::RestrictionConstraint) + result |= SchemaType::RestrictionConstraint; + if (constraints & NamedSchemaComponent::ExtensionConstraint) + result |= SchemaType::ExtensionConstraint; + + return result; +} + +bool XsdSchemaHelper::isValidlySubstitutable(const SchemaType::Ptr &type, const SchemaType::Ptr &otherType, const SchemaType::DerivationConstraints &constraints) +{ + // @see http://www.w3.org/TR/xmlschema11-1/#key-val-sub-type + + // 1 + if (type->isComplexType() && otherType->isComplexType()) { + SchemaType::DerivationConstraints keywords = constraints; + if (otherType->isDefinedBySchema()) + keywords |= convertBlockingConstraints(XsdComplexType::Ptr(otherType)->prohibitedSubstitutions()); + + return isComplexDerivationOk(type, otherType, keywords); + } + + // 2 + if (type->isComplexType() && otherType->isSimpleType()) { + return isComplexDerivationOk(type, otherType, constraints); + } + + // 3 + if (type->isSimpleType() && otherType->isSimpleType()) { + return isSimpleDerivationOk(type, otherType, constraints); + } + + return false; +} + +bool XsdSchemaHelper::isSimpleDerivationOk(const SchemaType::Ptr &derivedType, const SchemaType::Ptr baseType, const SchemaType::DerivationConstraints &constraints) +{ + // @see http://www.w3.org/TR/xmlschema11-1/#cos-st-derived-ok + + // 1 + if (derivedType == baseType) + return true; + + // 2.1 + if ((constraints & SchemaType::RestrictionConstraint) || derivedType->wxsSuperType()->derivationConstraints() & SchemaType::RestrictionConstraint) { + return false; + } + + // 2.2.1 + if (derivedType->wxsSuperType() == baseType) + return true; + + // 2.2.2 + if (derivedType->wxsSuperType() != BuiltinTypes::xsAnyType) { + if (isSimpleDerivationOk(derivedType->wxsSuperType(), baseType, constraints)) + return true; + } + + // 2.2.3 + if (derivedType->category() == SchemaType::SimpleTypeList || derivedType->category() == SchemaType::SimpleTypeUnion) { + if (baseType == BuiltinTypes::xsAnySimpleType) + return true; + } + + // 2.2.4 + if (baseType->category() == SchemaType::SimpleTypeUnion && baseType->isDefinedBySchema()) { // 2.2.4.1 + const AnySimpleType::List memberTypes = XsdSimpleType::Ptr(baseType)->memberTypes(); + for (int i = 0; i < memberTypes.count(); ++i) { + if (isSimpleDerivationOk(derivedType, memberTypes.at(i), constraints)) { // 2.2.4.2 + if (XsdSimpleType::Ptr(baseType)->facets().isEmpty()) { // 2.2.4.3 + return true; + } + } + } + } + + return false; +} + +bool XsdSchemaHelper::isComplexDerivationOk(const SchemaType::Ptr &derivedType, const SchemaType::Ptr baseType, const SchemaType::DerivationConstraints &constraints) +{ + if (!derivedType) + return false; + + // @see http://www.w3.org/TR/xmlschema11-1/#cos-ct-derived-ok + + // 1 + if (derivedType != baseType) { + if ((derivedType->derivationMethod() == SchemaType::DerivationRestriction) && (constraints & SchemaType::RestrictionConstraint)) + return false; + if ((derivedType->derivationMethod() == SchemaType::DerivationExtension) && (constraints & SchemaType::ExtensionConstraint)) + return false; + } + + // 2.1 + if (derivedType == baseType) + return true; + + // 2.2 + if (derivedType->wxsSuperType() == baseType) + return true; + + // 2.3 + bool isOk = true; + if (derivedType->wxsSuperType() == BuiltinTypes::xsAnyType) { // 2.3.1 + isOk = false; + } else { // 2.3.2 + if (!derivedType->wxsSuperType()) + return false; + + if (derivedType->wxsSuperType()->isComplexType()) { // 2.3.2.1 + isOk = isComplexDerivationOk(derivedType->wxsSuperType(), baseType, constraints); + } else { // 2.3.2.2 + isOk = isSimpleDerivationOk(derivedType->wxsSuperType(), baseType, constraints); + } + } + if (isOk) + return true; + + return false; +} + +bool XsdSchemaHelper::constructAndCompare(const DerivedString::Ptr &operand1, + const AtomicComparator::Operator op, + const DerivedString::Ptr &operand2, + const SchemaType::Ptr &type, + const ReportContext::Ptr &context, + const SourceLocationReflection *const sourceLocationReflection) +{ + Q_ASSERT_X(type->category() == SchemaType::SimpleTypeAtomic, Q_FUNC_INFO, + "We can only compare atomic values."); + + // we can not cast a xs:String to a xs:QName, so lets go the safe way + if (type->name(context->namePool()) == BuiltinTypes::xsQName->name(context->namePool())) + return false; + + const AtomicValue::Ptr value1 = ValueFactory::fromLexical(operand1->stringValue(), type, context, sourceLocationReflection); + if (value1->hasError()) + return false; + + const AtomicValue::Ptr value2 = ValueFactory::fromLexical(operand2->stringValue(), type, context, sourceLocationReflection); + if (value2->hasError()) + return false; + + return ComparisonFactory::compare(value1, op, value2, type, context, sourceLocationReflection); +} + +bool XsdSchemaHelper::checkWildcardProcessContents(const XsdWildcard::Ptr &baseWildcard, const XsdWildcard::Ptr &derivedWildcard) +{ + if (baseWildcard->processContents() == XsdWildcard::Strict) { + if (derivedWildcard->processContents() == XsdWildcard::Lax || derivedWildcard->processContents() == XsdWildcard::Skip) { + return false; + } + } else if (baseWildcard->processContents() == XsdWildcard::Lax) { + if (derivedWildcard->processContents() == XsdWildcard::Skip) + return false; + } + + return true; +} + +bool XsdSchemaHelper::foundSubstitutionGroupTransitive(const XsdElement::Ptr &head, const XsdElement::Ptr &member, QSet &visitedElements) +{ + if (visitedElements.contains(member)) + return false; + else + visitedElements.insert(member); + + if (member->substitutionGroupAffiliations().isEmpty()) + return false; + + if (member->substitutionGroupAffiliations().contains(head)) { + return true; + } else { + const XsdElement::List affiliations = member->substitutionGroupAffiliations(); + for (int i = 0; i < affiliations.count(); ++i) { + if (foundSubstitutionGroupTransitive(head, affiliations.at(i), visitedElements)) + return true; + } + + return false; + } +} + +void XsdSchemaHelper::foundSubstitutionGroupTypeInheritance(const SchemaType::Ptr &headType, const SchemaType::Ptr &memberType, + QSet &derivationSet, NamedSchemaComponent::BlockingConstraints &blockSet) +{ + if (!memberType) + return; + + if (memberType == headType) + return; + + derivationSet.insert(memberType->derivationMethod()); + + if (memberType->isComplexType()) { + const XsdComplexType::Ptr complexType(memberType); + blockSet |= complexType->prohibitedSubstitutions(); + } + + foundSubstitutionGroupTypeInheritance(headType, memberType->wxsSuperType(), derivationSet, blockSet); +} + +bool XsdSchemaHelper::substitutionGroupOkTransitive(const XsdElement::Ptr &head, const XsdElement::Ptr &member, const NamePool::Ptr &namePool) +{ + // @see http://www.w3.org/TR/xmlschema11-1/#cos-equiv-derived-ok-rec + + // 1 + if ((member->name(namePool) == head->name(namePool)) && (member->type() == head->type())) + return true; + + // 2.1 + if (head->disallowedSubstitutions() & NamedSchemaComponent::SubstitutionConstraint) + return false; + + // 2.2 + { + QSet visitedElements; + if (!foundSubstitutionGroupTransitive(head, member, visitedElements)) + return false; + } + + // 2.3 + { + QSet derivationSet; + NamedSchemaComponent::BlockingConstraints blockSet; + + foundSubstitutionGroupTypeInheritance(head->type(), member->type(), derivationSet, blockSet); + + NamedSchemaComponent::BlockingConstraints checkSet(blockSet); + checkSet |= head->disallowedSubstitutions(); + if (head->type()->isComplexType()) { + const XsdComplexType::Ptr complexType(head->type()); + checkSet |= complexType->prohibitedSubstitutions(); + } + + if ((checkSet & NamedSchemaComponent::RestrictionConstraint) && derivationSet.contains(SchemaType::DerivationRestriction)) + return false; + if ((checkSet & NamedSchemaComponent::ExtensionConstraint) && derivationSet.contains(SchemaType::DerivationExtension)) + return false; + if (checkSet & NamedSchemaComponent::SubstitutionConstraint) + return false; + } + + return true; +} + +bool XsdSchemaHelper::isValidAttributeGroupRestriction(const XsdAttributeGroup::Ptr &derivedAttributeGroup, const XsdAttributeGroup::Ptr &attributeGroup, const XsdSchemaContext::Ptr &context, QString &errorMsg) +{ + // @see http://www.w3.org/TR/xmlschema-1/#derivation-ok-restriction + + const XsdAttributeUse::List derivedAttributeUses = derivedAttributeGroup->attributeUses(); + const XsdAttributeUse::List baseAttributeUses = attributeGroup->attributeUses(); + + return isValidAttributeUsesRestriction(derivedAttributeUses, baseAttributeUses, + derivedAttributeGroup->wildcard(), attributeGroup->wildcard(), context, errorMsg); +} + +bool XsdSchemaHelper::isValidAttributeUsesRestriction(const XsdAttributeUse::List &derivedAttributeUses, const XsdAttributeUse::List &baseAttributeUses, + const XsdWildcard::Ptr &derivedWildcard, const XsdWildcard::Ptr &wildcard, const XsdSchemaContext::Ptr &context, QString &errorMsg) +{ + const NamePool::Ptr namePool(context->namePool()); + + QHash baseAttributeUsesLookup; + for (int i = 0; i < baseAttributeUses.count(); ++i) + baseAttributeUsesLookup.insert(baseAttributeUses.at(i)->attribute()->name(namePool), baseAttributeUses.at(i)); + + QHash derivedAttributeUsesLookup; + for (int i = 0; i < derivedAttributeUses.count(); ++i) + derivedAttributeUsesLookup.insert(derivedAttributeUses.at(i)->attribute()->name(namePool), derivedAttributeUses.at(i)); + + // 2 + for (int i = 0; i < derivedAttributeUses.count(); ++i) { + const XsdAttributeUse::Ptr derivedAttributeUse = derivedAttributeUses.at(i); + + // prohibited attributes are no real attributes, so skip them in that test here + if (derivedAttributeUse->useType() == XsdAttributeUse::ProhibitedUse) + continue; + + if (baseAttributeUsesLookup.contains(derivedAttributeUse->attribute()->name(namePool))) { + const XsdAttributeUse::Ptr baseAttributeUse(baseAttributeUsesLookup.value(derivedAttributeUse->attribute()->name(namePool))); + + // 2.1.1 + if (baseAttributeUse->isRequired() == true && derivedAttributeUse->isRequired() == false) { + errorMsg = QtXmlPatterns::tr("base attribute %1 is required but derived attribute is not").arg(formatAttribute(baseAttributeUse->attribute()->displayName(namePool))); + return false; + } + + // 2.1.2 + if (!isSimpleDerivationOk(derivedAttributeUse->attribute()->type(), baseAttributeUse->attribute()->type(), SchemaType::DerivationConstraints())) { + errorMsg = QtXmlPatterns::tr("type of derived attribute %1 cannot be validly derived from type of base attribute").arg(formatAttribute(derivedAttributeUse->attribute()->displayName(namePool))); + return false; + } + + // 2.1.3 + XsdAttributeUse::ValueConstraint::Ptr derivedConstraint; + if (derivedAttributeUse->valueConstraint()) + derivedConstraint = derivedAttributeUse->valueConstraint(); + else if (derivedAttributeUse->attribute()->valueConstraint()) + derivedConstraint = XsdAttributeUse::ValueConstraint::fromAttributeValueConstraint(derivedAttributeUse->attribute()->valueConstraint()); + + XsdAttributeUse::ValueConstraint::Ptr baseConstraint; + if (baseAttributeUse->valueConstraint()) + baseConstraint = baseAttributeUse->valueConstraint(); + else if (baseAttributeUse->attribute()->valueConstraint()) + baseConstraint = XsdAttributeUse::ValueConstraint::fromAttributeValueConstraint(baseAttributeUse->attribute()->valueConstraint()); + + bool ok = false; + if (!baseConstraint || baseConstraint->variety() == XsdAttributeUse::ValueConstraint::Default) + ok = true; + + if (derivedConstraint && baseConstraint) { + const XsdTypeChecker checker(context, QVector(), QSourceLocation(QUrl(QLatin1String("http://dummy.org")), 1, 1)); + if (derivedConstraint->variety() == XsdAttributeUse::ValueConstraint::Fixed && checker.valuesAreEqual(derivedConstraint->value(), baseConstraint->value(), baseAttributeUse->attribute()->type())) + ok = true; + } + + if (!ok) { + errorMsg = QtXmlPatterns::tr("value constraint of derived attribute %1 does not match value constraint of base attribute").arg(formatAttribute(derivedAttributeUse->attribute()->displayName(namePool))); + return false; + } + } else { + if (!wildcard) { + errorMsg = QtXmlPatterns::tr("derived attribute %1 does not exists in the base definition").arg(formatAttribute(derivedAttributeUse->attribute()->displayName(namePool))); + return false; + } + + QXmlName name = derivedAttributeUse->attribute()->name(namePool); + + // wildcards using XsdWildcard::absentNamespace, so we have to fix that here + if (name.namespaceURI() == StandardNamespaces::empty) + name.setNamespaceURI(namePool->allocateNamespace(XsdWildcard::absentNamespace())); + + if (!wildcardAllowsExpandedName(name, wildcard, namePool)) { + errorMsg = QtXmlPatterns::tr("derived attribute %1 does not match the wildcard in the base definition").arg(formatAttribute(derivedAttributeUse->attribute()->displayName(namePool))); + return false; + } + } + } + + // 3 + for (int i = 0; i < baseAttributeUses.count(); ++i) { + const XsdAttributeUse::Ptr baseAttributeUse = baseAttributeUses.at(i); + + if (baseAttributeUse->isRequired()) { + if (derivedAttributeUsesLookup.contains(baseAttributeUse->attribute()->name(namePool))) { + if (!derivedAttributeUsesLookup.value(baseAttributeUse->attribute()->name(namePool))->isRequired()) { + errorMsg = QtXmlPatterns::tr("base attribute %1 is required but derived attribute is not").arg(formatAttribute(baseAttributeUse->attribute()->displayName(namePool))); + return false; + } + } else { + errorMsg = QtXmlPatterns::tr("base attribute %1 is required but missing in derived definition").arg(formatAttribute(baseAttributeUse->attribute()->displayName(namePool))); + return false; + } + } + } + + // 4 + if (derivedWildcard) { + if (!wildcard) { + errorMsg = QtXmlPatterns::tr("derived definition contains an %1 element that does not exists in the base definition").arg(formatElement("anyAttribute")); + return false; + } + + if (!isWildcardSubset(derivedWildcard, wildcard)) { + errorMsg = QtXmlPatterns::tr("derived wildcard is not a subset of the base wildcard"); + return false; + } + + if (!checkWildcardProcessContents(wildcard, derivedWildcard)) { + errorMsg = QtXmlPatterns::tr("%1 of derived wildcard is not a valid restriction of %2 of base wildcard").arg(formatKeyword("processContents")).arg(formatKeyword("processContents")); + return false; + } + } + + return true; +} + +bool XsdSchemaHelper::isValidAttributeUsesExtension(const XsdAttributeUse::List &derivedAttributeUses, const XsdAttributeUse::List &attributeUses, + const XsdWildcard::Ptr &derivedWildcard, const XsdWildcard::Ptr &wildcard, const XsdSchemaContext::Ptr &context, QString &errorMsg) +{ + // @see http://www.w3.org/TR/xmlschema11-1/#cos-ct-extends + + const NamePool::Ptr namePool(context->namePool()); + + // 1.2 + QHash lookupHash; + for (int i = 0; i < derivedAttributeUses.count(); ++i) + lookupHash.insert(derivedAttributeUses.at(i)->attribute()->name(namePool), derivedAttributeUses.at(i)->attribute()); + + for (int i = 0; i < attributeUses.count(); ++i) { + const QXmlName attributeName = attributeUses.at(i)->attribute()->name(namePool); + if (!lookupHash.contains(attributeName)) { + errorMsg = QtXmlPatterns::tr("attribute %1 from base type is missing in derived type").arg(formatKeyword(namePool->displayName(attributeName))); + return false; + } + + if (lookupHash.value(attributeName)->type() != attributeUses.at(i)->attribute()->type()) { + errorMsg = QtXmlPatterns::tr("type of derived attribute %1 differs from type of base attribute").arg(formatKeyword(namePool->displayName(attributeName))); + return false; + } + } + + // 1.3 + if (wildcard) { + if (!derivedWildcard) { + errorMsg = QtXmlPatterns::tr("base definition contains an %1 element that is missing in the derived definition").arg(formatElement("anyAttribute")); + return false; + } + } + + return true; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdschemahelper_p.h b/src/xmlpatterns/schema/qxsdschemahelper_p.h new file mode 100644 index 0000000..1722b4c --- /dev/null +++ b/src/xmlpatterns/schema/qxsdschemahelper_p.h @@ -0,0 +1,156 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdSchemaHelper_H +#define Patternist_XsdSchemaHelper_H + +#include "qcomparisonfactory_p.h" +#include "qschematype_p.h" +#include "qxsdattributegroup_p.h" +#include "qxsdelement_p.h" +#include "qxsdparticle_p.h" +#include "qxsdschemacontext_p.h" +#include "qxsdwildcard_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + + /** + * @short Contains helper methods that are used by XsdSchemaParser, XsdSchemaResolver and XsdSchemaChecker. + * + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdSchemaHelper + { + public: + /** + * Checks whether the given @p particle is emptiable as defined by the + * algorithm in the schema spec. + */ + static bool isParticleEmptiable(const XsdParticle::Ptr &particle); + + /** + * Checks whether the given @p nameSpace is allowed by the given namespace @p constraint. + */ + static bool wildcardAllowsNamespaceName(const QString &nameSpace, const XsdWildcard::NamespaceConstraint::Ptr &constraint); + + /** + * Checks whether the given @p name is allowed by the namespace constraint of the given @p wildcard. + */ + static bool wildcardAllowsExpandedName(const QXmlName &name, const XsdWildcard::Ptr &wildcard, const NamePool::Ptr &namePool); + + /** + * Checks whether the @p wildcard is a subset of @p otherWildcard. + */ + static bool isWildcardSubset(const XsdWildcard::Ptr &wildcard, const XsdWildcard::Ptr &otherWildcard); + + /** + * Returns the union of the given @p wildcard and @p otherWildcard. + */ + static XsdWildcard::Ptr wildcardUnion(const XsdWildcard::Ptr &wildcard, const XsdWildcard::Ptr &otherWildcard); + + /** + * Returns the intersection of the given @p wildcard and @p otherWildcard. + */ + static XsdWildcard::Ptr wildcardIntersection(const XsdWildcard::Ptr &wildcard, const XsdWildcard::Ptr &otherWildcard); + + /** + * Returns whether the given @p type is validly substitutable for an @p otherType + * under the given @p constraints. + */ + static bool isValidlySubstitutable(const SchemaType::Ptr &type, const SchemaType::Ptr &otherType, const SchemaType::DerivationConstraints &constraints); + + /** + * Returns whether the simple @p derivedType can be derived from the simple @p baseType + * under the given @p constraints. + */ + static bool isSimpleDerivationOk(const SchemaType::Ptr &derivedType, const SchemaType::Ptr baseType, const SchemaType::DerivationConstraints &constraints); + + /** + * Returns whether the complex @p derivedType can be derived from the complex @p baseType + * under the given @p constraints. + */ + static bool isComplexDerivationOk(const SchemaType::Ptr &derivedType, const SchemaType::Ptr baseType, const SchemaType::DerivationConstraints &constraints); + + /** + * This method takes the two string based operands @p operand1 and @p operand2 and converts them to instances of type @p type. + * If the conversion fails, @c false is returned, otherwise the instances are compared by the given operator @p op and the + * result of the comparison is returned. + */ + static bool constructAndCompare(const DerivedString::Ptr &operand1, + const AtomicComparator::Operator op, + const DerivedString::Ptr &operand2, + const SchemaType::Ptr &type, + const ReportContext::Ptr &context, + const SourceLocationReflection *const sourceLocationReflection); + + /** + * Returns whether the process content property of the @p derivedWildcard is valid + * according to the process content property of its @p baseWildcard. + */ + static bool checkWildcardProcessContents(const XsdWildcard::Ptr &baseWildcard, const XsdWildcard::Ptr &derivedWildcard); + + /** + * Checks whether @[ member is a member of the substitution group with the given @p head. + */ + static bool foundSubstitutionGroupTransitive(const XsdElement::Ptr &head, const XsdElement::Ptr &member, QSet &visitedElements); + + /** + * A helper method that iterates over the type hierarchy from @p memberType up to @p headType and collects all + * @p derivationSet and @p blockSet constraints that exists on the way there. + */ + static void foundSubstitutionGroupTypeInheritance(const SchemaType::Ptr &headType, const SchemaType::Ptr &memberType, + QSet &derivationSet, NamedSchemaComponent::BlockingConstraints &blockSet); + + /** + * Checks if the @p member is transitive to @p head. + */ + static bool substitutionGroupOkTransitive(const XsdElement::Ptr &head, const XsdElement::Ptr &member, const NamePool::Ptr &namePool); + + /** + * Checks if @p derivedAttributeGroup is a valid restriction for @p attributeGroup. + */ + static bool isValidAttributeGroupRestriction(const XsdAttributeGroup::Ptr &derivedAttributeGroup, const XsdAttributeGroup::Ptr &attributeGroup, const XsdSchemaContext::Ptr &context, QString &errorMsg); + + /** + * Checks if @p derivedAttributeUses are a valid restriction for @p attributeUses. + */ + static bool isValidAttributeUsesRestriction(const XsdAttributeUse::List &derivedAttributeUses, const XsdAttributeUse::List &attributeUses, + const XsdWildcard::Ptr &derivedWildcard, const XsdWildcard::Ptr &wildcard, const XsdSchemaContext::Ptr &context, QString &errorMsg); + + /** + * Checks if @p derivedAttributeUses are a valid extension for @p attributeUses. + */ + static bool isValidAttributeUsesExtension(const XsdAttributeUse::List &derivedAttributeUses, const XsdAttributeUse::List &attributeUses, + const XsdWildcard::Ptr &derivedWildcard, const XsdWildcard::Ptr &wildcard, const XsdSchemaContext::Ptr &context, QString &errorMsg); + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsdschemamerger.cpp b/src/xmlpatterns/schema/qxsdschemamerger.cpp new file mode 100644 index 0000000..a924c9c --- /dev/null +++ b/src/xmlpatterns/schema/qxsdschemamerger.cpp @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qxsdschemamerger_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +XsdSchemaMerger::XsdSchemaMerger(const XsdSchema::Ptr &schema, const XsdSchema::Ptr &otherSchema) +{ + merge(schema, otherSchema); +} + +XsdSchema::Ptr XsdSchemaMerger::mergedSchema() const +{ + return m_mergedSchema; +} + +void XsdSchemaMerger::merge(const XsdSchema::Ptr &schema, const XsdSchema::Ptr &otherSchema) +{ + m_mergedSchema = XsdSchema::Ptr(new XsdSchema(otherSchema->namePool())); + + // first fill the merged schema with the values from schema + if (schema) { + const XsdElement::List elements = schema->elements(); + for (int i = 0; i < elements.count(); ++i) { + m_mergedSchema->addElement(elements.at(i)); + } + + const XsdAttribute::List attributes = schema->attributes(); + for (int i = 0; i < attributes.count(); ++i) { + m_mergedSchema->addAttribute(attributes.at(i)); + } + + const SchemaType::List types = schema->types(); + for (int i = 0; i < types.count(); ++i) { + m_mergedSchema->addType(types.at(i)); + } + + const SchemaType::List anonymousTypes = schema->anonymousTypes(); + for (int i = 0; i < anonymousTypes.count(); ++i) { + m_mergedSchema->addAnonymousType(anonymousTypes.at(i)); + } + + const XsdModelGroup::List elementGroups = schema->elementGroups(); + for (int i = 0; i < elementGroups.count(); ++i) { + m_mergedSchema->addElementGroup(elementGroups.at(i)); + } + + const XsdAttributeGroup::List attributeGroups = schema->attributeGroups(); + for (int i = 0; i < attributeGroups.count(); ++i) { + m_mergedSchema->addAttributeGroup(attributeGroups.at(i)); + } + + const XsdNotation::List notations = schema->notations(); + for (int i = 0; i < notations.count(); ++i) { + m_mergedSchema->addNotation(notations.at(i)); + } + + const XsdIdentityConstraint::List identityConstraints = schema->identityConstraints(); + for (int i = 0; i < identityConstraints.count(); ++i) { + m_mergedSchema->addIdentityConstraint(identityConstraints.at(i)); + } + } + + // then merge in the values from the otherSchema + { + const XsdElement::List elements = otherSchema->elements(); + for (int i = 0; i < elements.count(); ++i) { + if (!m_mergedSchema->element(elements.at(i)->name(otherSchema->namePool()))) + m_mergedSchema->addElement(elements.at(i)); + } + + const XsdAttribute::List attributes = otherSchema->attributes(); + for (int i = 0; i < attributes.count(); ++i) { + if (!m_mergedSchema->attribute(attributes.at(i)->name(otherSchema->namePool()))) + m_mergedSchema->addAttribute(attributes.at(i)); + } + + const SchemaType::List types = otherSchema->types(); + for (int i = 0; i < types.count(); ++i) { + if (!m_mergedSchema->type(types.at(i)->name(otherSchema->namePool()))) + m_mergedSchema->addType(types.at(i)); + } + + const SchemaType::List anonymousTypes = otherSchema->anonymousTypes(); + for (int i = 0; i < anonymousTypes.count(); ++i) { + // add anonymous type as they are + m_mergedSchema->addAnonymousType(anonymousTypes.at(i)); + } + + const XsdModelGroup::List elementGroups = otherSchema->elementGroups(); + for (int i = 0; i < elementGroups.count(); ++i) { + if (!m_mergedSchema->elementGroup(elementGroups.at(i)->name(otherSchema->namePool()))) + m_mergedSchema->addElementGroup(elementGroups.at(i)); + } + + const XsdAttributeGroup::List attributeGroups = otherSchema->attributeGroups(); + for (int i = 0; i < attributeGroups.count(); ++i) { + if (!m_mergedSchema->attributeGroup(attributeGroups.at(i)->name(otherSchema->namePool()))) + m_mergedSchema->addAttributeGroup(attributeGroups.at(i)); + } + + const XsdNotation::List notations = otherSchema->notations(); + for (int i = 0; i < notations.count(); ++i) { + if (!m_mergedSchema->notation(notations.at(i)->name(otherSchema->namePool()))) + m_mergedSchema->addNotation(notations.at(i)); + } + + const XsdIdentityConstraint::List identityConstraints = otherSchema->identityConstraints(); + for (int i = 0; i < identityConstraints.count(); ++i) { + if (!m_mergedSchema->identityConstraint(identityConstraints.at(i)->name(otherSchema->namePool()))) + m_mergedSchema->addIdentityConstraint(identityConstraints.at(i)); + } + } +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdschemamerger_p.h b/src/xmlpatterns/schema/qxsdschemamerger_p.h new file mode 100644 index 0000000..54cc0f2 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdschemamerger_p.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdSchemaMerger_H +#define Patternist_XsdSchemaMerger_H + +#include "qxsdschema_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short A helper class that merges two schemas into one. + * + * This class is used in XsdValidatingInstanceReader to merge the schema + * given in the constructor with a schema defined in the instance document + * via xsi:schemaLocation or xsi:noNamespaceSchema location. + * + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdSchemaMerger : public QSharedData + { + public: + typedef QExplicitlySharedDataPointer Ptr; + + /** + * Creates a new schema merger object that merges @p schema with @p otherSchema. + */ + XsdSchemaMerger(const XsdSchema::Ptr &schema, const XsdSchema::Ptr &otherSchema); + + /** + * Returns the merged schema. + */ + XsdSchema::Ptr mergedSchema() const; + + private: + void merge(const XsdSchema::Ptr &schema, const XsdSchema::Ptr &otherSchema); + + XsdSchema::Ptr m_mergedSchema; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsdschemaparser.cpp b/src/xmlpatterns/schema/qxsdschemaparser.cpp new file mode 100644 index 0000000..9f1e75d --- /dev/null +++ b/src/xmlpatterns/schema/qxsdschemaparser.cpp @@ -0,0 +1,6012 @@ + +#include "qxsdschemaparser_p.h" + +#include "private/qxmlutils_p.h" +#include "qacceltreeresourceloader_p.h" +#include "qautoptr_p.h" +#include "qboolean_p.h" +#include "qderivedinteger_p.h" +#include "qderivedstring_p.h" +#include "qqnamevalue_p.h" +#include "qxmlquery_p.h" +#include "qxpathhelper_p.h" +#include "qxsdattributereference_p.h" +#include "qxsdreference_p.h" +#include "qxsdschematoken_p.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +/** + * @page schema_overview Overview + * @section structure_and_components Structure and Components + * + * The schema validator code consists of 4 major components + * + *
+ *
The schema parser (QPatternist::XsdSchemaParser)
+ *
This component parses a XML document that is supplied via a QIODevice. It creates + * a so called (incomplete) 'compiled schema', which is a representation of the XML Schema + * structure as C++ objects. + * As the parser is a streaming parser, it can't resolve references to types or elements/attributes + * in place, therefor it creates resolver tasks which are passed to the schema resolver component + * for resolving at a later point in time. + * The parser does furthermore the basic XML structure constraint checking, e.g. if all required + * attributes are available or the order of the elements is correct.
+ * + *
The schema resolver (QPatternist::XsdSchemaResolver)
+ *
This component is activated after the schema parser component has been finished the parsing + * of all schemas. The resolver has been supplied with resolve tasks by the schema parser that + * it will resolve in this step now. Between working on the single resolver tasks, the resolver + * calls check methods from the schema checker component to make sure that some assertions are + * valid (e.g. no circular inheritance of types), so that the resolver can work without hassle. + * During resoving references to attribute or element groups it also checks for circular references + * of these groups. + * At the end of that phase we have a compiled schema that is fully resolved (not necessarily valid though).
+ * + *
The schema checker (QPatternist::XsdSchemaChecker)
+ *
This component does all the schema constraint checking as given by the Schema specification. + * At the end of that phase we have fully resolved and valid compiled schema that can be used for validation + * of instance documents.
+ * + *
The validator (QPatternist::XsdValidatingInstanceReader)
+ *
This component is responsible for validating a XML instance document, provided via a QIODevice, against + * a valid compiled schema.
+ *
+ * + * @ingroup Patternist_schema + */ + +using namespace QPatternist; + +namespace QPatternist +{ + +/** + * @short A helper class for automatically handling namespace scopes of elements. + * + * This class should be instantiated at the beginning of each parse XYZ method. + */ +class ElementNamespaceHandler +{ + public: + /** + * Creates a new element namespace handler object. + * + * It checks whether the @p parser is on the right @p tag and it creates a new namespace + * context that contains the inherited and local namespace declarations. + */ + ElementNamespaceHandler(const XsdSchemaToken::NodeName &tag, XsdSchemaParser *parser) + : m_parser(parser) + { + Q_ASSERT(m_parser->isStartElement() && (XsdSchemaToken::toToken(m_parser->name()) == tag) && (XsdSchemaToken::toToken(m_parser->namespaceUri()) == XsdSchemaToken::XML_NS_SCHEMA_URI)); + m_parser->m_namespaceSupport.pushContext(); + m_parser->m_namespaceSupport.setPrefixes(m_parser->namespaceDeclarations()); + } + + /** + * Destroys the element namespace handler object. + * + * It destroys the local namespace context. + */ + ~ElementNamespaceHandler() + { + m_parser->m_namespaceSupport.popContext(); + } + + private: + XsdSchemaParser *m_parser; +}; + +/** + * A helper class that checks for the right occurrence of + * xml tags with the help of a DFA. + */ +class TagValidationHandler +{ + public: + TagValidationHandler(XsdTagScope::Type tag, XsdSchemaParser *parser, const NamePool::Ptr &namePool) + : m_parser(parser), m_machine(namePool) + { + Q_ASSERT(m_parser->m_stateMachines.contains(tag)); + + m_machine = m_parser->m_stateMachines.value(tag); + m_machine.reset(); + } + + void validate(XsdSchemaToken::NodeName token) + { + if (token == XsdSchemaToken::NoKeyword) { + m_parser->error(QtXmlPatterns::tr("can not process unknown element %1").arg(formatElement(m_parser->name().toString()))); + return; + } + + if (!m_machine.proceed(token)) { + m_parser->error(QtXmlPatterns::tr("element %1 is not allowed in this scope").arg(formatElement(XsdSchemaToken::toString(token)))); + return; + } + } + + void finalize() const + { + if (!m_machine.inEndState()) { + m_parser->error(QtXmlPatterns::tr("child element is missing in that scope")); + } + } + + private: + XsdSchemaParser *m_parser; + XsdStateMachine m_machine; +}; + +} + +/** + * Returns a list of all particles with group references that appear at any level of + * the given unresolved @p group. + */ +static XsdParticle::List collectGroupRef(const XsdModelGroup::Ptr &group) +{ + XsdParticle::List refParticles; + + XsdParticle::List particles = group->particles(); + for (int i = 0; i < particles.count(); ++i) { + if (particles.at(i)->term()->isReference()) { + const XsdReference::Ptr reference(particles.at(i)->term()); + if (reference->type() == XsdReference::ModelGroup) + refParticles.append(particles.at(i)); + } + if (particles.at(i)->term()->isModelGroup()) { + refParticles << collectGroupRef(XsdModelGroup::Ptr(particles.at(i)->term())); + } + } + + return refParticles; +} + +/** + * Helper function that works around the limited facilities of + * QUrl/AnyURI::fromLexical to detect invalid URIs + */ +inline static bool isValidUri(const QString &string) +{ + // an empty URI points to the current document as defined in RFC 2396 (4.2) + if (string.isEmpty()) + return true; + + // explicit check as that is not checked by the code below + if (string.startsWith(QLatin1String("##"))) + return false; + + const AnyURI::Ptr uri = AnyURI::fromLexical(string); + return (!(uri->hasError())); +} + +XsdSchemaParser::XsdSchemaParser(const XsdSchemaContext::Ptr &context, const XsdSchemaParserContext::Ptr &parserContext, QIODevice *device) + : MaintainingReader(parserContext->elementDescriptions(), QSet(), context, device) + , m_context(context) + , m_parserContext(parserContext) + , m_namePool(m_parserContext->namePool()) + , m_namespaceSupport(m_namePool) +{ + m_schema = m_parserContext->schema(); + m_schemaResolver = m_parserContext->resolver(); + m_idCache = XsdIdCache::Ptr(new XsdIdCache()); + + setupStateMachines(); + setupBuiltinTypeNames(); +} + +void XsdSchemaParser::setIncludedSchemas(const NamespaceSet &schemas) +{ + m_includedSchemas = schemas; +} + +void XsdSchemaParser::setImportedSchemas(const NamespaceSet &schemas) +{ + m_importedSchemas = schemas; +} + +void XsdSchemaParser::setRedefinedSchemas(const NamespaceSet &schemas) +{ + m_redefinedSchemas = schemas; +} + +void XsdSchemaParser::setTargetNamespace(const QString &targetNamespace) +{ + m_targetNamespace = targetNamespace; +} + +void XsdSchemaParser::setTargetNamespaceExtended(const QString &targetNamespace) +{ + m_targetNamespace = targetNamespace; + m_namespaceSupport.setTargetNamespace(m_namePool->allocateNamespace(m_targetNamespace)); +} + +void XsdSchemaParser::setDocumentURI(const QUrl &uri) +{ + qDebug("%s", qPrintable(uri.toString())); + m_documentURI = uri; + + // prevent to get included/imported/redefined twice + m_includedSchemas.insert(uri); + m_importedSchemas.insert(uri); +} + +QUrl XsdSchemaParser::documentURI() const +{ + return m_documentURI; +} + +bool XsdSchemaParser::isAnyAttributeAllowed() const +{ + return false; +} + +bool XsdSchemaParser::parse(ParserType parserType) +{ + m_componentLocationHash.clear(); + + while (!atEnd()) { + readNext(); + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + if (isSchemaTag(XsdSchemaToken::Schema, token, namespaceToken)) { + parseSchema(parserType); + } else { + error(QtXmlPatterns::tr("document is not a XML schema")); + } + } + } + + m_schemaResolver->addComponentLocationHash(m_componentLocationHash); + m_schemaResolver->setDefaultOpenContent(m_defaultOpenContent, m_defaultOpenContentAppliesToEmpty); + + return true; +} + +void XsdSchemaParser::error(const QString &msg) +{ + MaintainingReader::error(msg, XsdSchemaContext::XSDError); +} + +void XsdSchemaParser::attributeContentError(const char *attributeName, const char *elementName, const QString &value, const SchemaType::Ptr &type) +{ + if (type) { + error(QtXmlPatterns::tr("%1 attribute of %2 element contains invalid content: {%3} is not a value of type %4") + .arg(formatAttribute(attributeName)) + .arg(formatElement(elementName)) + .arg(formatData(value)) + .arg(formatType(m_namePool, type))); + } else { + error(QtXmlPatterns::tr("%1 attribute of %2 element contains invalid content: {%3}") + .arg(formatAttribute(attributeName)) + .arg(formatElement(elementName)) + .arg(formatData(value))); + } +} + +void XsdSchemaParser::parseSchema(ParserType parserType) +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Schema, this); + + validateElement(XsdTagScope::Schema); + + // parse attributes + + if (parserType == TopLevelParser) { + if (hasAttribute(QString::fromLatin1("targetNamespace"))) { + m_targetNamespace = readNamespaceAttribute(QString::fromLatin1("targetNamespace"), "schema"); + } + } else if (parserType == IncludeParser) { + // m_targetNamespace is set to the target namespace of the including schema at this point + + if (hasAttribute(QString::fromLatin1("targetNamespace"))) { + const QString targetNamespace = readNamespaceAttribute(QString::fromLatin1("targetNamespace"), "schema"); + + if (m_targetNamespace != targetNamespace) { + error(QtXmlPatterns::tr("target namespace %1 of included schema is different from the target namespace %2 as defined by the including schema") + .arg(formatURI(targetNamespace)).arg(formatURI(m_targetNamespace))); + return; + } + } + } else if (parserType == ImportParser) { + // m_targetNamespace is set to the target namespace from the namespace attribute of the tag at this point + + QString targetNamespace; + if (hasAttribute(QString::fromLatin1("targetNamespace"))) { + targetNamespace = readNamespaceAttribute(QString::fromLatin1("targetNamespace"), "schema"); + } + + if (m_targetNamespace != targetNamespace) { + error(QtXmlPatterns::tr("target namespace %1 of imported schema is different from the target namespace %2 as defined by the importing schema") + .arg(formatURI(targetNamespace)).arg(formatURI(m_targetNamespace))); + return; + } + } else if (parserType == RedefineParser) { + // m_targetNamespace is set to the target namespace of the redefining schema at this point + + if (hasAttribute(QString::fromLatin1("targetNamespace"))) { + const QString targetNamespace = readNamespaceAttribute(QString::fromLatin1("targetNamespace"), "schema"); + + if (m_targetNamespace != targetNamespace) { + error(QtXmlPatterns::tr("target namespace %1 of imported schema is different from the target namespace %2 as defined by the importing schema") + .arg(formatURI(targetNamespace)).arg(formatURI(m_targetNamespace))); + return; + } + } + } + + if (hasAttribute(QString::fromLatin1("attributeFormDefault"))) { + const QString value = readAttribute(QString::fromLatin1("attributeFormDefault")); + if (value != QString::fromLatin1("qualified") && value != QString::fromLatin1("unqualified")) { + attributeContentError("attributeFormDefault", "schema", value); + return; + } + + m_attributeFormDefault = value; + } else { + m_attributeFormDefault = QString::fromLatin1("unqualified"); + } + + if (hasAttribute(QString::fromLatin1("elementFormDefault"))) { + const QString value = readAttribute(QString::fromLatin1("elementFormDefault")); + if (value != QString::fromLatin1("qualified") && value != QString::fromLatin1("unqualified")) { + attributeContentError("elementFormDefault", "schema", value); + return; + } + + m_elementFormDefault = value; + } else { + m_elementFormDefault = QString::fromLatin1("unqualified"); + } + + if (hasAttribute(QString::fromLatin1("blockDefault"))) { + const QString blockDefault = readAttribute(QString::fromLatin1("blockDefault")); + const QStringList blockDefaultList = blockDefault.split(QLatin1Char(' '), QString::SkipEmptyParts); + for (int i = 0; i < blockDefaultList.count(); ++i) { + const QString value = blockDefaultList.at(i); + if (value != QString::fromLatin1("#all") && + value != QString::fromLatin1("extension") && + value != QString::fromLatin1("restriction") && + value != QString::fromLatin1("substitution")) { + attributeContentError("blockDefault", "schema", value); + return; + } + } + + m_blockDefault = blockDefault; + } + + if (hasAttribute(QString::fromLatin1("finalDefault"))) { + const QString finalDefault = readAttribute(QString::fromLatin1("finalDefault")); + const QStringList finalDefaultList = finalDefault.split(QLatin1Char(' '), QString::SkipEmptyParts); + for (int i = 0; i < finalDefaultList.count(); ++i) { + const QString value = finalDefaultList.at(i); + if (value != QString::fromLatin1("#all") && + value != QString::fromLatin1("extension") && + value != QString::fromLatin1("restriction") && + value != QString::fromLatin1("list") && + value != QString::fromLatin1("union")) { + attributeContentError("finalDefault", "schema", value); + return; + } + } + + m_finalDefault = finalDefault; + } + + if (hasAttribute(QString::fromLatin1("xpathDefaultNamespace"))) { + const QString xpathDefaultNamespace = readAttribute(QString::fromLatin1("xpathDefaultNamespace")); + if (xpathDefaultNamespace != QString::fromLatin1("##defaultNamespace") && + xpathDefaultNamespace != QString::fromLatin1("##targetNamespace") && + xpathDefaultNamespace != QString::fromLatin1("##local")) { + if (!isValidUri(xpathDefaultNamespace)) { + attributeContentError("xpathDefaultNamespace", "schema", xpathDefaultNamespace); + return; + } + } + m_xpathDefaultNamespace = xpathDefaultNamespace; + } else { + m_xpathDefaultNamespace = QString::fromLatin1("##local"); + } + + if (hasAttribute(QString::fromLatin1("defaultAttributes"))) { + const QString attrGroupName = readQNameAttribute(QString::fromLatin1("defaultAttributes"), "schema"); + convertName(attrGroupName, NamespaceSupport::ElementName, m_defaultAttributes); // translate qualified name into QXmlName + } + + if (hasAttribute(QString::fromLatin1("version"))) { + const QString version = readAttribute(QString::fromLatin1("version")); + } + + if (hasAttribute(QString::fromLatin1("http://www.w3.org/XML/1998/namespace"), QString::fromLatin1("lang"))) { + const QString value = readAttribute(QString::fromLatin1("lang"), QString::fromLatin1("http://www.w3.org/XML/1998/namespace")); + + const QRegExp exp(QString::fromLatin1("[a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*")); + if (!exp.exactMatch(value)) { + attributeContentError("xml:lang", "schema", value); + return; + } + } + + validateIdAttribute("schema"); + + TagValidationHandler tagValidator(XsdTagScope::Schema, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Include, token, namespaceToken)) { + parseInclude(); + } else if (isSchemaTag(XsdSchemaToken::Import, token, namespaceToken)) { + parseImport(); + } else if (isSchemaTag(XsdSchemaToken::Redefine, token, namespaceToken)) { + parseRedefine(); + } else if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + m_schema->addAnnotation(annotation); + } else if (isSchemaTag(XsdSchemaToken::DefaultOpenContent, token, namespaceToken)) { + parseDefaultOpenContent(); + } else if (isSchemaTag(XsdSchemaToken::SimpleType, token, namespaceToken)) { + const XsdSimpleType::Ptr type = parseGlobalSimpleType(); + addType(type); + } else if (isSchemaTag(XsdSchemaToken::ComplexType, token, namespaceToken)) { + const XsdComplexType::Ptr type = parseGlobalComplexType(); + addType(type); + } else if (isSchemaTag(XsdSchemaToken::Group, token, namespaceToken)) { + const XsdModelGroup::Ptr group = parseNamedGroup(); + addElementGroup(group); + } else if (isSchemaTag(XsdSchemaToken::AttributeGroup, token, namespaceToken)) { + XsdAttributeGroup::Ptr attributeGroup = parseNamedAttributeGroup(); + addAttributeGroup(attributeGroup); + } else if (isSchemaTag(XsdSchemaToken::Element, token, namespaceToken)) { + const XsdElement::Ptr element = parseGlobalElement(); + addElement(element); + } else if (isSchemaTag(XsdSchemaToken::Attribute, token, namespaceToken)) { + const XsdAttribute::Ptr attribute = parseGlobalAttribute(); + addAttribute(attribute); + } else if (isSchemaTag(XsdSchemaToken::Notation, token, namespaceToken)) { + const XsdNotation::Ptr notation = parseNotation(); + addNotation(notation); + } else { + parseUnknown(); + } + } + } + + tagValidator.finalize(); + + m_schema->setTargetNamespace(m_targetNamespace); +} + +void XsdSchemaParser::parseInclude() +{ + Q_ASSERT(isStartElement() && XsdSchemaToken::toToken(name()) == XsdSchemaToken::Include && + XsdSchemaToken::toToken(namespaceUri()) == XsdSchemaToken::XML_NS_SCHEMA_URI); + + validateElement(XsdTagScope::Include); + + // parse attributes + const QString schemaLocation = readAttribute(QString::fromLatin1("schemaLocation")); + + QUrl url(schemaLocation); + if (url.isRelative()) { + Q_ASSERT(m_documentURI.isValid()); + + url = m_documentURI.resolved(url); + } + + if (m_includedSchemas.contains(url)) { + // we have included that file already, according to the schema spec we are + // allowed to silently skip it. + } else { + m_includedSchemas.insert(url); + + const AutoPtr reply(AccelTreeResourceLoader::load(url, m_context->networkAccessManager(), + m_context, AccelTreeResourceLoader::ContinueOnError)); + if (reply) { + // parse the included schema by a different parser but with the same context + XsdSchemaParser parser(m_context, m_parserContext, reply.data()); + parser.setDocumentURI(url); + parser.setTargetNamespaceExtended(m_targetNamespace); + parser.setIncludedSchemas(m_includedSchemas); + parser.setImportedSchemas(m_importedSchemas); + parser.setRedefinedSchemas(m_redefinedSchemas); + if (!parser.parse(XsdSchemaParser::IncludeParser)) + return; + } + } + + validateIdAttribute("include"); + + TagValidationHandler tagValidator(XsdTagScope::Include, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + m_schema->addAnnotation(annotation); + } else { + parseUnknown(); + } + } + } + + tagValidator.finalize(); +} + +void XsdSchemaParser::parseImport() +{ + Q_ASSERT(isStartElement() && XsdSchemaToken::toToken(name()) == XsdSchemaToken::Import && + XsdSchemaToken::toToken(namespaceUri()) == XsdSchemaToken::XML_NS_SCHEMA_URI); + + validateElement(XsdTagScope::Import); + + // parse attributes + QString importNamespace; + if (hasAttribute(QString::fromLatin1("namespace"))) { + importNamespace = readAttribute(QString::fromLatin1("namespace")); + if (importNamespace == m_targetNamespace) { + error(QtXmlPatterns::tr("%1 element is not allowed to have the same %2 attribute value as the target namespace %3") + .arg(formatElement("import")) + .arg(formatAttribute("namespace")) + .arg(formatURI(m_targetNamespace))); + return; + } + } else { + if (m_targetNamespace.isEmpty()) { + error(QtXmlPatterns::tr("%1 element without %2 attribute is not allowed inside schema without target namespace") + .arg(formatElement("import")) + .arg(formatAttribute("namespace"))); + return; + } + } + + if (hasAttribute(QString::fromLatin1("schemaLocation"))) { + const QString schemaLocation = readAttribute(QString::fromLatin1("schemaLocation")); + + QUrl url(schemaLocation); + if (url.isRelative()) { + Q_ASSERT(m_documentURI.isValid()); + + url = m_documentURI.resolved(url); + } + + if (m_importedSchemas.contains(url)) { + // we have imported that file already, according to the schema spec we are + // allowed to silently skip it. + } else { + m_importedSchemas.insert(url); + + // as it is possible that well known schemas (e.g. XSD for XML) are only referenced by + // namespace we should add it as well + m_importedSchemas.insert(importNamespace); + + AutoPtr reply(AccelTreeResourceLoader::load(url, m_context->networkAccessManager(), + m_context, AccelTreeResourceLoader::ContinueOnError)); + if (reply) { + // parse the included schema by a different parser but with the same context + XsdSchemaParser parser(m_context, m_parserContext, reply.data()); + parser.setDocumentURI(url); + parser.setTargetNamespace(importNamespace); + parser.setIncludedSchemas(m_includedSchemas); + parser.setImportedSchemas(m_importedSchemas); + parser.setRedefinedSchemas(m_redefinedSchemas); + if (!parser.parse(XsdSchemaParser::ImportParser)) + return; + } + } + } else { + // check whether it is a known namespace we have a builtin schema for + if (!importNamespace.isEmpty()) { + if (!m_importedSchemas.contains(importNamespace)) { + m_importedSchemas.insert(importNamespace); + + QFile file(QString::fromLatin1(":") + importNamespace); + if (file.open(QIODevice::ReadOnly)) { + XsdSchemaParser parser(m_context, m_parserContext, &file); + parser.setDocumentURI(importNamespace); + parser.setTargetNamespace(importNamespace); + parser.setIncludedSchemas(m_includedSchemas); + parser.setImportedSchemas(m_importedSchemas); + parser.setRedefinedSchemas(m_redefinedSchemas); + if (!parser.parse(XsdSchemaParser::ImportParser)) + return; + } + } + } else { + // we don't import anything... that is valid according to the schema + } + } + + validateIdAttribute("import"); + + TagValidationHandler tagValidator(XsdTagScope::Import, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + m_schema->addAnnotation(annotation); + } else { + parseUnknown(); + } + } + } + + tagValidator.finalize(); +} + +void XsdSchemaParser::parseRedefine() +{ + Q_ASSERT(isStartElement() && XsdSchemaToken::toToken(name()) == XsdSchemaToken::Redefine && + XsdSchemaToken::toToken(namespaceUri()) == XsdSchemaToken::XML_NS_SCHEMA_URI); + + validateElement(XsdTagScope::Redefine); + + // parse attributes + validateIdAttribute("redefine"); + + const QString schemaLocation = readAttribute(QString::fromLatin1("schemaLocation")); + + TagValidationHandler tagValidator(XsdTagScope::Redefine, this, m_namePool); + + XsdSimpleType::List redefinedSimpleTypes; + XsdComplexType::List redefinedComplexTypes; + XsdModelGroup::List redefinedGroups; + XsdAttributeGroup::List redefinedAttributeGroups; + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + m_schema->addAnnotation(annotation); + } else if (isSchemaTag(XsdSchemaToken::SimpleType, token, namespaceToken)) { + const XsdSimpleType::Ptr type = parseGlobalSimpleType(); + redefinedSimpleTypes.append(type); + + const QXmlName baseTypeName = m_parserContext->resolver()->baseTypeNameOfType(type); + if (baseTypeName != type->name(m_namePool)) { + error(QString::fromLatin1("redefined simple type %1 must have itself as base type").arg(formatType(m_namePool, type))); + return; + } + } else if (isSchemaTag(XsdSchemaToken::ComplexType, token, namespaceToken)) { + const XsdComplexType::Ptr type = parseGlobalComplexType(); + redefinedComplexTypes.append(type); + + // @see http://www.w3.org/TR/xmlschema11-1/#src-redefine + + // 5 + const QXmlName baseTypeName = m_parserContext->resolver()->baseTypeNameOfType(type); + if (baseTypeName != type->name(m_namePool)) { + error(QString::fromLatin1("redefined complex type %1 must have itself as base type").arg(formatType(m_namePool, type))); + return; + } + } else if (isSchemaTag(XsdSchemaToken::Group, token, namespaceToken)) { + const XsdModelGroup::Ptr group = parseNamedGroup(); + redefinedGroups.append(group); + } else if (isSchemaTag(XsdSchemaToken::AttributeGroup, token, namespaceToken)) { + const XsdAttributeGroup::Ptr group = parseNamedAttributeGroup(); + redefinedAttributeGroups.append(group); + + } else { + parseUnknown(); + } + } + } + + bool locationMustResolve = false; + if (!redefinedSimpleTypes.isEmpty() || !redefinedComplexTypes.isEmpty() || + !redefinedGroups.isEmpty() || !redefinedAttributeGroups.isEmpty()) { + locationMustResolve = true; + } + + QUrl url(schemaLocation); + if (url.isRelative()) { + Q_ASSERT(m_documentURI.isValid()); + + url = m_documentURI.resolved(url); + } + + // we parse the schema given in the redefine tag into its own context + const XsdSchemaParserContext::Ptr redefinedContext(new XsdSchemaParserContext(m_namePool, m_context)); + + if (m_redefinedSchemas.contains(url)) { + // we have redefined that file already, according to the schema spec we are + // allowed to silently skip it. + } else { + m_redefinedSchemas.insert(url); + QNetworkReply *reply = AccelTreeResourceLoader::load(url, m_context->networkAccessManager(), + m_context, + (locationMustResolve ? AccelTreeResourceLoader::FailOnError : AccelTreeResourceLoader::ContinueOnError)); + if (reply) { + // parse the included schema by a different parser but with the same context + XsdSchemaParser parser(m_context, redefinedContext, reply); + parser.setDocumentURI(url); + parser.setTargetNamespaceExtended(m_targetNamespace); + parser.setIncludedSchemas(m_includedSchemas); + parser.setImportedSchemas(m_importedSchemas); + parser.setRedefinedSchemas(m_redefinedSchemas); + if (!parser.parse(XsdSchemaParser::RedefineParser)) + return; + + delete reply; + } + } + + XsdSimpleType::List contextSimpleTypes = redefinedContext->schema()->simpleTypes(); + XsdComplexType::List contextComplexTypes = redefinedContext->schema()->complexTypes(); + XsdModelGroup::List contextGroups = redefinedContext->schema()->elementGroups(); + XsdAttributeGroup::List contextAttributeGroups = redefinedContext->schema()->attributeGroups(); + + // now we do the actual redefinition: + + // iterate over all redefined simple types + for (int i = 0; i < redefinedSimpleTypes.count(); ++i) { + XsdSimpleType::Ptr redefinedType = redefinedSimpleTypes.at(i); + + //TODONEXT: validation + + // search the definition they override in the context types + bool found = false; + for (int j = 0; j < contextSimpleTypes.count(); ++j) { + XsdSimpleType::Ptr contextType = contextSimpleTypes.at(j); + + if (redefinedType->name(m_namePool) == contextType->name(m_namePool)) { // we found the right type + found = true; + + // 1) set name of context type to empty name + contextType->setName(m_parserContext->createAnonymousName(QString())); + + // 2) set the context type as base type for the redefined type + redefinedType->setWxsSuperType(contextType); + + // 3) remove the base type resolving job from the resolver as + // we have set the base type here explicitely + m_parserContext->resolver()->removeSimpleRestrictionBase(redefinedType); + + // 4) add the redefined type to the schema + addType(redefinedType); + + // 5) add the context type as anonymous type, so the resolver + // can resolve it further. + addAnonymousType(contextType); + + // 6) remove the context type from the list + contextSimpleTypes.removeAt(j); + + break; + } + } + + if (!found) { + error(QString::fromLatin1("no matching type found to redefine simple type %1").arg(formatType(m_namePool, redefinedType))); + return; + } + } + + // add all remaining context simple types to the schema + for (int i = 0; i < contextSimpleTypes.count(); ++i) { + addType(contextSimpleTypes.at(i)); + } + + // iterate over all redefined complex types + for (int i = 0; i < redefinedComplexTypes.count(); ++i) { + XsdComplexType::Ptr redefinedType = redefinedComplexTypes.at(i); + + //TODONEXT: validation + + // search the definition they override in the context types + bool found = false; + for (int j = 0; j < contextComplexTypes.count(); ++j) { + XsdComplexType::Ptr contextType = contextComplexTypes.at(j); + + if (redefinedType->name(m_namePool) == contextType->name(m_namePool)) { // we found the right type + found = true; + + // 1) set name of context type to empty name + contextType->setName(m_parserContext->createAnonymousName(QString())); + + // 2) set the context type as base type for the redefined type + redefinedType->setWxsSuperType(contextType); + + // 3) remove the base type resolving job from the resolver as + // we have set the base type here explicitely + m_parserContext->resolver()->removeComplexBaseType(redefinedType); + + // 4) add the redefined type to the schema + addType(redefinedType); + + // 5) add the context type as anonymous type, so the resolver + // can resolve its attribute uses etc. + addAnonymousType(contextType); + + // 6) remove the context type from the list + contextComplexTypes.removeAt(j); + + break; + } + } + + if (!found) { + error(QString::fromLatin1("no matching type found to redefine complex type %1").arg(formatType(m_namePool, redefinedType))); + return; + } + } + + // iterate over all redefined element groups + for (int i = 0; i < redefinedGroups.count(); ++i) { + const XsdModelGroup::Ptr group(redefinedGroups.at(i)); + + // @see http://www.w3.org/TR/xmlschema11-1/#src-redefine + + // 6 + const XsdParticle::List particles = collectGroupRef(group); + XsdParticle::Ptr referencedParticle; + int sameNameCounter = 0; + for (int i = 0; i < particles.count(); ++i) { + const XsdReference::Ptr ref(particles.at(i)->term()); + if (ref->referenceName() == group->name(m_namePool)) { + referencedParticle = particles.at(i); + + if (referencedParticle->minimumOccurs() != 1 || referencedParticle->maximumOccurs() != 1 || referencedParticle->maximumOccursUnbounded()) { // 6.1.2 + error(QString::fromLatin1("redefined group %1 can not contain reference to itself with minOccurs or maxOccurs != 1").arg(formatKeyword(group->displayName(m_namePool)))); + return; + } + sameNameCounter++; + } + } + + // 6.1.1 + if (sameNameCounter > 1) { + error(QString::fromLatin1("redefined group %1 can not contain multiple references to itself").arg(formatKeyword(group->displayName(m_namePool)))); + return; + } + + // search the group definition in the included schema (S2) + XsdModelGroup::Ptr contextGroup; + for (int j = 0; j < contextGroups.count(); ++j) { + if (group->name(m_namePool) == contextGroups.at(j)->name(m_namePool)) { + contextGroup = contextGroups.at(j); + break; + } + } + + if (!contextGroup) { // 6.2.1 + error(QString::fromLatin1("redefined group %1 has no occurrence in included schema").arg(formatKeyword(group->displayName(m_namePool)))); + return; + } + + if (sameNameCounter == 1) { + // there was a self reference in the redefined group, so use the + // group from the included schema + + // set a anonymous name to the group of the included schema + contextGroup->setName(m_parserContext->createAnonymousName(m_namePool->stringForNamespace(contextGroup->name(m_namePool).namespaceURI()))); + + // replace the self-reference with the group from the included schema + referencedParticle->setTerm(contextGroup); + + addElementGroup(group); + + addElementGroup(contextGroup); + contextGroups.removeAll(contextGroup); + } else { + // there was no self reference in the redefined group + + // just add the redefined group... + addElementGroup(group); + + // we have to add them, otherwise it is not resolved and we can't validate it later + contextGroup->setName(m_parserContext->createAnonymousName(m_namePool->stringForNamespace(contextGroup->name(m_namePool).namespaceURI()))); + addElementGroup(contextGroup); + + m_schemaResolver->addRedefinedGroups(group, contextGroup); + + // ...and forget about the group from the included schema + contextGroups.removeAll(contextGroup); + } + } + + // iterate over all redefined attribute groups + for (int i = 0; i < redefinedAttributeGroups.count(); ++i) { + const XsdAttributeGroup::Ptr group(redefinedAttributeGroups.at(i)); + + // @see http://www.w3.org/TR/xmlschema11-1/#src-redefine + + // 7 + + // 7.1 + int sameNameCounter = 0; + for (int j = 0; j < group->attributeUses().count(); ++j) { + const XsdAttributeUse::Ptr attributeUse(group->attributeUses().at(j)); + if (attributeUse->isReference()) { + const XsdAttributeReference::Ptr reference(attributeUse); + if (reference->type() == XsdAttributeReference::AttributeGroup) { + if (group->name(m_namePool) == reference->referenceName()) + sameNameCounter++; + } + } + } + if (sameNameCounter > 1) { + error(QString::fromLatin1("redefined attribute group %1 can not contain multiple references to itself").arg(formatKeyword(group->displayName(m_namePool)))); + return; + } + + // search the attribute group definition in the included schema (S2) + XsdAttributeGroup::Ptr baseGroup; + for (int j = 0; j < contextAttributeGroups.count(); ++j) { + const XsdAttributeGroup::Ptr contextGroup(contextAttributeGroups.at(j)); + if (group->name(m_namePool) == contextGroup->name(m_namePool)) { + baseGroup = contextGroup; + break; + } + } + + if (!baseGroup) { // 7.2.1 + error(QString::fromLatin1("redefined attribute group %1 has no occurrence in included schema").arg(formatKeyword(group->displayName(m_namePool)))); + return; + } + + if (sameNameCounter == 1) { + + // first set an anonymous name to the attribute group from the included + // schema + baseGroup->setName(m_parserContext->createAnonymousName(m_namePool->stringForNamespace(baseGroup->name(m_namePool).namespaceURI()))); + + // iterate over the attribute uses of the redefined attribute group + // and replace the self-reference with the attribute group from the + // included schema + for (int j = 0; j < group->attributeUses().count(); ++j) { + const XsdAttributeUse::Ptr attributeUse(group->attributeUses().at(j)); + if (attributeUse->isReference()) { + const XsdAttributeReference::Ptr reference(attributeUse); + if (reference->type() == XsdAttributeReference::AttributeGroup) { + if (group->name(m_namePool) == reference->referenceName()) { + reference->setReferenceName(baseGroup->name(m_namePool)); + break; + } + } + } + } + + // add both groups to the target schema + addAttributeGroup(baseGroup); + addAttributeGroup(group); + + contextAttributeGroups.removeAll(baseGroup); + } + + if (sameNameCounter == 0) { // 7.2 + + // we have to add them, otherwise it is not resolved and we can't validate it later + baseGroup->setName(m_parserContext->createAnonymousName(m_namePool->stringForNamespace(baseGroup->name(m_namePool).namespaceURI()))); + addAttributeGroup(baseGroup); + + m_schemaResolver->addRedefinedAttributeGroups(group, baseGroup); + + // just add the redefined attribute group to the target schema... + addAttributeGroup(group); + + // ... and forget about the one from the included schema + contextAttributeGroups.removeAll(baseGroup); + } + } + + // add all remaining context complex types to the schema + for (int i = 0; i < contextComplexTypes.count(); ++i) { + addType(contextComplexTypes.at(i)); + } + + // add all remaining context element groups to the schema + for (int i = 0; i < contextGroups.count(); ++i) { + addElementGroup(contextGroups.at(i)); + } + + // add all remaining context attribute groups to the schema + for (int i = 0; i < contextAttributeGroups.count(); ++i) { + addAttributeGroup(contextAttributeGroups.at(i)); + } + + // copy all elements, attributes and notations + const XsdElement::List contextElements = redefinedContext->schema()->elements(); + for (int i = 0; i < contextElements.count(); ++i) { + addElement(contextElements.at(i)); + } + + const XsdAttribute::List contextAttributes = redefinedContext->schema()->attributes(); + for (int i = 0; i < contextAttributes.count(); ++i) { + addAttribute(contextAttributes.at(i)); + } + + const XsdNotation::List contextNotations = redefinedContext->schema()->notations(); + for (int i = 0; i < contextNotations.count(); ++i) { + addNotation(contextNotations.at(i)); + } + + // push all data to resolve from the context resolver to our resolver + redefinedContext->resolver()->copyDataTo(m_parserContext->resolver()); + + tagValidator.finalize(); +} + +XsdAnnotation::Ptr XsdSchemaParser::parseAnnotation() +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Annotation, this); + + validateElement(XsdTagScope::Annotation); + + // parse attributes + validateIdAttribute("annotation"); + + TagValidationHandler tagValidator(XsdTagScope::Annotation, this, m_namePool); + + const XsdAnnotation::Ptr annotation(new XsdAnnotation()); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Appinfo, token, namespaceToken)) { + const XsdApplicationInformation::Ptr info = parseAppInfo(); + annotation->addApplicationInformation(info); + } else if (isSchemaTag(XsdSchemaToken::Documentation, token, namespaceToken)) { + const XsdDocumentation::Ptr documentation = parseDocumentation(); + annotation->addDocumentation(documentation); + } else { + parseUnknown(); + } + } + } + + tagValidator.finalize(); + + return annotation; +} + +XsdApplicationInformation::Ptr XsdSchemaParser::parseAppInfo() +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Appinfo, this); + + validateElement(XsdTagScope::AppInfo); + + const XsdApplicationInformation::Ptr info(new XsdApplicationInformation()); + + // parse attributes + if (hasAttribute(QString::fromLatin1("source"))) { + const QString value = readAttribute(QString::fromLatin1("source")); + + if (!isValidUri(value)) { + attributeContentError("source", "appinfo", value, BuiltinTypes::xsAnyURI); + return info; + } + + if (!value.isEmpty()) { + const AnyURI::Ptr source = AnyURI::fromLexical(value); + info->setSource(source); + } + } + + while (!atEnd()) { //EVAL: can be anything... what to do? + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) + parseUnknownDocumentation(); + } + + return info; +} + +XsdDocumentation::Ptr XsdSchemaParser::parseDocumentation() +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Documentation, this); + + validateElement(XsdTagScope::Documentation); + + const XsdDocumentation::Ptr documentation(new XsdDocumentation()); + + // parse attributes + if (hasAttribute(QString::fromLatin1("source"))) { + const QString value = readAttribute(QString::fromLatin1("source")); + + if (!isValidUri(value)) { + attributeContentError("source", "documentation", value, BuiltinTypes::xsAnyURI); + return documentation; + } + + if (!value.isEmpty()) { + const AnyURI::Ptr source = AnyURI::fromLexical(value); + documentation->setSource(source); + } + } + + if (hasAttribute(QString::fromLatin1("http://www.w3.org/XML/1998/namespace"), QString::fromLatin1("lang"))) { + const QString value = readAttribute(QString::fromLatin1("lang"), QString::fromLatin1("http://www.w3.org/XML/1998/namespace")); + + const QRegExp exp(QString::fromLatin1("[a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*")); + if (!exp.exactMatch(value)) { + attributeContentError("xml:lang", "documentation", value); + return documentation; + } + } + + while (!atEnd()) { //EVAL: can by any... what to do? + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) + parseUnknownDocumentation(); + } + + return documentation; +} + +void XsdSchemaParser::parseDefaultOpenContent() +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::DefaultOpenContent, this); + + validateElement(XsdTagScope::DefaultOpenContent); + + m_defaultOpenContent = XsdComplexType::OpenContent::Ptr(new XsdComplexType::OpenContent()); + + if (hasAttribute(QString::fromLatin1("appliesToEmpty"))) { + const QString value = readAttribute(QString::fromLatin1("appliesToEmpty")); + const Boolean::Ptr appliesToEmpty = Boolean::fromLexical(value); + if (appliesToEmpty->hasError()) { + attributeContentError("appliesToEmpty", "defaultOpenContent", value, BuiltinTypes::xsBoolean); + return; + } + + m_defaultOpenContentAppliesToEmpty = appliesToEmpty->as()->value(); + } else { + m_defaultOpenContentAppliesToEmpty = false; + } + + if (hasAttribute(QString::fromLatin1("mode"))) { + const QString mode = readAttribute(QString::fromLatin1("mode")); + + if (mode == QString::fromLatin1("interleave")) { + m_defaultOpenContent->setMode(XsdComplexType::OpenContent::Interleave); + } else if (mode == QString::fromLatin1("suffix")) { + m_defaultOpenContent->setMode(XsdComplexType::OpenContent::Suffix); + } else { + attributeContentError("mode", "defaultOpenContent", mode); + return; + } + } else { + m_defaultOpenContent->setMode(XsdComplexType::OpenContent::Interleave); + } + + validateIdAttribute("defaultOpenContent"); + + TagValidationHandler tagValidator(XsdTagScope::DefaultOpenContent, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + m_defaultOpenContent->addAnnotation(annotation); + } else if (isSchemaTag(XsdSchemaToken::Any, token, namespaceToken)) { + const XsdParticle::Ptr particle; + const XsdWildcard::Ptr wildcard = parseAny(particle); + m_defaultOpenContent->setWildcard(wildcard); + } else { + parseUnknown(); + } + } + } + + tagValidator.finalize(); +} + +XsdSimpleType::Ptr XsdSchemaParser::parseGlobalSimpleType() +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::SimpleType, this); + + validateElement(XsdTagScope::GlobalSimpleType); + + const XsdSimpleType::Ptr simpleType(new XsdSimpleType()); + simpleType->setCategory(XsdSimpleType::SimpleTypeAtomic); // just to make sure it's not invalid + + // parse attributes + const SchemaType::DerivationConstraints allowedConstraints(SchemaType::ExtensionConstraint | SchemaType::RestrictionConstraint | SchemaType::ListConstraint | SchemaType::UnionConstraint); + simpleType->setDerivationConstraints(readDerivationConstraintAttribute(allowedConstraints, "simpleType")); + + const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("simpleType")); + simpleType->setName(objectName); + + validateIdAttribute("simpleType"); + + TagValidationHandler tagValidator(XsdTagScope::GlobalSimpleType, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + simpleType->addAnnotation(annotation); + } else if (isSchemaTag(XsdSchemaToken::Restriction, token, namespaceToken)) { + parseSimpleRestriction(simpleType); + } else if (isSchemaTag(XsdSchemaToken::List, token, namespaceToken)) { + parseList(simpleType); + } else if (isSchemaTag(XsdSchemaToken::Union, token, namespaceToken)) { + parseUnion(simpleType); + } else { + parseUnknown(); + } + } + } + + tagValidator.finalize(); + + return simpleType; +} + +XsdSimpleType::Ptr XsdSchemaParser::parseLocalSimpleType() +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::SimpleType, this); + + validateElement(XsdTagScope::LocalSimpleType); + + const XsdSimpleType::Ptr simpleType(new XsdSimpleType()); + simpleType->setCategory(XsdSimpleType::SimpleTypeAtomic); // just to make sure it's not invalid + simpleType->setName(m_parserContext->createAnonymousName(m_targetNamespace)); + + validateIdAttribute("simpleType"); + + TagValidationHandler tagValidator(XsdTagScope::LocalSimpleType, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + simpleType->addAnnotation(annotation); + } else if (isSchemaTag(XsdSchemaToken::Restriction, token, namespaceToken)) { + parseSimpleRestriction(simpleType); + } else if (isSchemaTag(XsdSchemaToken::List, token, namespaceToken)) { + parseList(simpleType); + } else if (isSchemaTag(XsdSchemaToken::Union, token, namespaceToken)) { + parseUnion(simpleType); + } else { + parseUnknown(); + } + } + } + + tagValidator.finalize(); + + return simpleType; +} + +void XsdSchemaParser::parseSimpleRestriction(const XsdSimpleType::Ptr &ptr) +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Restriction, this); + + validateElement(XsdTagScope::SimpleRestriction); + + ptr->setDerivationMethod(XsdSimpleType::DerivationRestriction); + + // The base attribute and simpleType member are mutually exclusive, + // so we keep track of that + bool hasBaseAttribute = false; + bool hasBaseTypeSpecified = false; + + QXmlName baseName; + if (hasAttribute(QString::fromLatin1("base"))) { + const QString base = readQNameAttribute(QString::fromLatin1("base"), "restriction"); + convertName(base, NamespaceSupport::ElementName, baseName); // translate qualified name into QXmlName + m_schemaResolver->addSimpleRestrictionBase(ptr, baseName, currentSourceLocation()); // add to resolver + + hasBaseAttribute = true; + hasBaseTypeSpecified = true; + } + validateIdAttribute("restriction"); + + XsdFacet::Hash facets; + QList patternFacets; + QList enumerationFacets; + QList assertionFacets; + + TagValidationHandler tagValidator(XsdTagScope::SimpleRestriction, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + ptr->addAnnotation(annotation); + } else if (isSchemaTag(XsdSchemaToken::SimpleType, token, namespaceToken)) { + if (hasBaseAttribute) { + error(QtXmlPatterns::tr("%1 element is not allowed inside %2 element if %3 attribute is present") + .arg(formatElement("simpleType")) + .arg(formatElement("restriction")) + .arg(formatAttribute("base"))); + return; + } + + const XsdSimpleType::Ptr type = parseLocalSimpleType(); + type->setContext(ptr); + ptr->setWxsSuperType(type); + ptr->setCategory(type->category()); + hasBaseTypeSpecified = true; + + // add it to list of anonymous types as well + addAnonymousType(type); + } else if (isSchemaTag(XsdSchemaToken::MinExclusive, token, namespaceToken)) { + const XsdFacet::Ptr facet = parseMinExclusiveFacet(); + addFacet(facet, facets, ptr); + } else if (isSchemaTag(XsdSchemaToken::MinInclusive, token, namespaceToken)) { + const XsdFacet::Ptr facet = parseMinInclusiveFacet(); + addFacet(facet, facets, ptr); + } else if (isSchemaTag(XsdSchemaToken::MaxExclusive, token, namespaceToken)) { + const XsdFacet::Ptr facet = parseMaxExclusiveFacet(); + addFacet(facet, facets, ptr); + } else if (isSchemaTag(XsdSchemaToken::MaxInclusive, token, namespaceToken)) { + const XsdFacet::Ptr facet = parseMaxInclusiveFacet(); + addFacet(facet, facets, ptr); + } else if (isSchemaTag(XsdSchemaToken::TotalDigits, token, namespaceToken)) { + const XsdFacet::Ptr facet = parseTotalDigitsFacet(); + addFacet(facet, facets, ptr); + } else if (isSchemaTag(XsdSchemaToken::FractionDigits, token, namespaceToken)) { + const XsdFacet::Ptr facet = parseFractionDigitsFacet(); + addFacet(facet, facets, ptr); + } else if (isSchemaTag(XsdSchemaToken::Length, token, namespaceToken)) { + const XsdFacet::Ptr facet = parseLengthFacet(); + addFacet(facet, facets, ptr); + } else if (isSchemaTag(XsdSchemaToken::MinLength, token, namespaceToken)) { + const XsdFacet::Ptr facet = parseMinLengthFacet(); + addFacet(facet, facets, ptr); + } else if (isSchemaTag(XsdSchemaToken::MaxLength, token, namespaceToken)) { + const XsdFacet::Ptr facet = parseMaxLengthFacet(); + addFacet(facet, facets, ptr); + } else if (isSchemaTag(XsdSchemaToken::Enumeration, token, namespaceToken)) { + const XsdFacet::Ptr facet = parseEnumerationFacet(); + enumerationFacets.append(facet); + } else if (isSchemaTag(XsdSchemaToken::WhiteSpace, token, namespaceToken)) { + const XsdFacet::Ptr facet = parseWhiteSpaceFacet(); + addFacet(facet, facets, ptr); + } else if (isSchemaTag(XsdSchemaToken::Pattern, token, namespaceToken)) { + const XsdFacet::Ptr facet = parsePatternFacet(); + patternFacets.append(facet); + } else if (isSchemaTag(XsdSchemaToken::Assertion, token, namespaceToken)) { + const XsdFacet::Ptr facet = parseAssertionFacet(); + assertionFacets.append(facet); + } else { + parseUnknown(); + } + } + } + + if (!hasBaseTypeSpecified) { + error(QtXmlPatterns::tr("%1 element has neither %2 attribute nor %3 child element") + .arg(formatElement("restriction")) + .arg(formatAttribute("base")) + .arg(formatElement("simpleType"))); + return; + } + + // merge all pattern facets into one multi value facet + if (!patternFacets.isEmpty()) { + const XsdFacet::Ptr patternFacet(new XsdFacet()); + patternFacet->setType(XsdFacet::Pattern); + + AtomicValue::List multiValue; + for (int i = 0; i < patternFacets.count(); ++i) + multiValue << patternFacets.at(i)->multiValue(); + + patternFacet->setMultiValue(multiValue); + addFacet(patternFacet, facets, ptr); + } + + // merge all enumeration facets into one multi value facet + if (!enumerationFacets.isEmpty()) { + const XsdFacet::Ptr enumerationFacet(new XsdFacet()); + enumerationFacet->setType(XsdFacet::Enumeration); + + AtomicValue::List multiValue; + for (int i = 0; i < enumerationFacets.count(); ++i) + multiValue << enumerationFacets.at(i)->multiValue(); + + enumerationFacet->setMultiValue(multiValue); + addFacet(enumerationFacet, facets, ptr); + } + + // merge all assertion facets into one facet + if (!assertionFacets.isEmpty()) { + const XsdFacet::Ptr assertionFacet(new XsdFacet()); + assertionFacet->setType(XsdFacet::Assertion); + + XsdAssertion::List assertions; + for (int i = 0; i < assertionFacets.count(); ++i) + assertions << assertionFacets.at(i)->assertions(); + + assertionFacet->setAssertions(assertions); + addFacet(assertionFacet, facets, ptr); + } + + ptr->setFacets(facets); + + tagValidator.finalize(); +} + +void XsdSchemaParser::parseList(const XsdSimpleType::Ptr &ptr) +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::List, this); + + validateElement(XsdTagScope::List); + + ptr->setCategory(XsdSimpleType::SimpleTypeList); + ptr->setDerivationMethod(XsdSimpleType::DerivationList); + ptr->setWxsSuperType(BuiltinTypes::xsAnySimpleType); + + // The itemType attribute and simpleType member are mutually exclusive, + // so we keep track of that + bool hasItemTypeAttribute = false; + bool hasItemTypeSpecified = false; + + if (hasAttribute(QString::fromLatin1("itemType"))) { + const QString itemType = readQNameAttribute(QString::fromLatin1("itemType"), "list"); + QXmlName typeName; + convertName(itemType, NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName + m_schemaResolver->addSimpleListType(ptr, typeName, currentSourceLocation()); // add to resolver + + hasItemTypeAttribute = true; + hasItemTypeSpecified = true; + } + + validateIdAttribute("list"); + + TagValidationHandler tagValidator(XsdTagScope::List, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + ptr->addAnnotation(annotation); + } else if (isSchemaTag(XsdSchemaToken::SimpleType, token, namespaceToken)) { + if (hasItemTypeAttribute) { + error(QtXmlPatterns::tr("%1 element is not allowed inside %2 element if %3 attribute is present") + .arg(formatElement("simpleType")) + .arg(formatElement("list")) + .arg(formatAttribute("itemType"))); + return; + } + + const XsdSimpleType::Ptr type = parseLocalSimpleType(); + type->setContext(ptr); + ptr->setItemType(type); + + hasItemTypeSpecified = true; + + // add it to list of anonymous types as well + addAnonymousType(type); + } else { + parseUnknown(); + } + } + } + + if (!hasItemTypeSpecified) { + error(QtXmlPatterns::tr("%1 element has neither %2 attribute nor %3 child element") + .arg(formatElement("list")) + .arg(formatAttribute("itemType")) + .arg(formatElement("simpleType"))); + return; + } + + tagValidator.finalize(); + + // add the default white space facet that every simple type with list derivation has + const XsdFacet::Ptr defaultFacet(new XsdFacet()); + defaultFacet->setType(XsdFacet::WhiteSpace); + defaultFacet->setFixed(true); + defaultFacet->setValue(DerivedString::fromLexical(m_namePool, XsdSchemaToken::toString(XsdSchemaToken::Collapse))); + XsdFacet::Hash facets; + facets.insert(defaultFacet->type(), defaultFacet); + ptr->setFacets(facets); +} + +void XsdSchemaParser::parseUnion(const XsdSimpleType::Ptr &ptr) +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Union, this); + + validateElement(XsdTagScope::Union); + + ptr->setCategory(XsdSimpleType::SimpleTypeUnion); + ptr->setDerivationMethod(XsdSimpleType::DerivationUnion); + ptr->setWxsSuperType(BuiltinTypes::xsAnySimpleType); + + // The memberTypes attribute is not allowed to be empty, + // so we keep track of that + bool hasMemberTypesAttribute = false; + bool hasMemberTypesSpecified = false; + + if (hasAttribute(QString::fromLatin1("memberTypes"))) { + hasMemberTypesAttribute = true; + + const QStringList memberTypes = readAttribute(QString::fromLatin1("memberTypes")).split(QLatin1Char(' '), QString::SkipEmptyParts); + QList typeNames; + + for (int i = 0; i < memberTypes.count(); ++i) { + QXmlName typeName; + convertName(memberTypes.at(i), NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName + typeNames.append(typeName); + } + + if (!typeNames.isEmpty()) { + m_schemaResolver->addSimpleUnionTypes(ptr, typeNames, currentSourceLocation()); // add to resolver + hasMemberTypesSpecified = true; + } + } + + validateIdAttribute("union"); + + AnySimpleType::List memberTypes; + + TagValidationHandler tagValidator(XsdTagScope::Union, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + ptr->addAnnotation(annotation); + } else if (isSchemaTag(XsdSchemaToken::SimpleType, token, namespaceToken)) { + const XsdSimpleType::Ptr type = parseLocalSimpleType(); + type->setContext(ptr); + memberTypes.append(type); + + // add it to list of anonymous types as well + addAnonymousType(type); + } else { + parseUnknown(); + } + } + } + + if (!memberTypes.isEmpty()) { + ptr->setMemberTypes(memberTypes); + hasMemberTypesSpecified = true; + } + + if (!hasMemberTypesSpecified) { + error(QtXmlPatterns::tr("%1 element has neither %2 attribute nor %3 child element") + .arg(formatElement("union")) + .arg(formatAttribute("memberTypes")) + .arg(formatElement("simpleType"))); + return; + } + + tagValidator.finalize(); +} + +XsdFacet::Ptr XsdSchemaParser::parseMinExclusiveFacet() +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::MinExclusive, this); + + validateElement(XsdTagScope::MinExclusiveFacet); + + const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet()); + facet->setType(XsdFacet::MinimumExclusive); + + // parse attributes + if (hasAttribute(QString::fromLatin1("fixed"))) { + const QString value = readAttribute(QString::fromLatin1("fixed")); + const Boolean::Ptr fixed = Boolean::fromLexical(value); + if (fixed->hasError()) { + attributeContentError("fixed", "minExclusive", value, BuiltinTypes::xsBoolean); + return facet; + } + + facet->setFixed(fixed->as()->value()); + } else { + facet->setFixed(false); // the default value + } + + // as minExclusive can have a value of type anySimpleType, we just read + // the string here and store it for later intepretation + const QString value = readAttribute(QString::fromLatin1("value")); + DerivedString::Ptr string = DerivedString::fromLexical(m_namePool, value); + if (string->hasError()) { + attributeContentError("value", "minExclusive", value, BuiltinTypes::xsAnySimpleType); + return facet; + } else { + facet->setValue(string); + } + + validateIdAttribute("minExclusive"); + + TagValidationHandler tagValidator(XsdTagScope::MinExclusiveFacet, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + facet->addAnnotation(annotation); + } else { + parseUnknown(); + } + } + } + + tagValidator.finalize(); + + return facet; +} + +XsdFacet::Ptr XsdSchemaParser::parseMinInclusiveFacet() +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::MinInclusive, this); + + validateElement(XsdTagScope::MinInclusiveFacet); + + const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet()); + facet->setType(XsdFacet::MinimumInclusive); + + // parse attributes + if (hasAttribute(QString::fromLatin1("fixed"))) { + const QString value = readAttribute(QString::fromLatin1("fixed")); + const Boolean::Ptr fixed = Boolean::fromLexical(value); + if (fixed->hasError()) { + attributeContentError("fixed", "minInclusive", value, BuiltinTypes::xsBoolean); + return facet; + } + + facet->setFixed(fixed->as()->value()); + } else { + facet->setFixed(false); // the default value + } + + // as minInclusive can have a value of type anySimpleType, we just read + // the string here and store it for later intepretation + const QString value = readAttribute(QString::fromLatin1("value")); + DerivedString::Ptr string = DerivedString::fromLexical(m_namePool, value); + if (string->hasError()) { + attributeContentError("value", "minInclusive", value, BuiltinTypes::xsAnySimpleType); + return facet; + } else { + facet->setValue(string); + } + + validateIdAttribute("minInclusive"); + + TagValidationHandler tagValidator(XsdTagScope::MinInclusiveFacet, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + facet->addAnnotation(annotation); + } else { + parseUnknown(); + } + } + } + + tagValidator.finalize(); + + return facet; +} + +XsdFacet::Ptr XsdSchemaParser::parseMaxExclusiveFacet() +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::MaxExclusive, this); + + validateElement(XsdTagScope::MaxExclusiveFacet); + + const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet()); + facet->setType(XsdFacet::MaximumExclusive); + + // parse attributes + if (hasAttribute(QString::fromLatin1("fixed"))) { + const QString value = readAttribute(QString::fromLatin1("fixed")); + const Boolean::Ptr fixed = Boolean::fromLexical(value); + if (fixed->hasError()) { + attributeContentError("fixed", "maxExclusive", value, BuiltinTypes::xsBoolean); + return facet; + } + + facet->setFixed(fixed->as()->value()); + } else { + facet->setFixed(false); // the default value + } + + // as maxExclusive can have a value of type anySimpleType, we just read + // the string here and store it for later intepretation + const QString value = readAttribute(QString::fromLatin1("value")); + DerivedString::Ptr string = DerivedString::fromLexical(m_namePool, value); + if (string->hasError()) { + attributeContentError("value", "maxExclusive", value, BuiltinTypes::xsAnySimpleType); + return facet; + } else { + facet->setValue(string); + } + + validateIdAttribute("maxExclusive"); + + TagValidationHandler tagValidator(XsdTagScope::MaxExclusiveFacet, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + facet->addAnnotation(annotation); + } else { + parseUnknown(); + } + } + } + + tagValidator.finalize(); + + return facet; +} + +XsdFacet::Ptr XsdSchemaParser::parseMaxInclusiveFacet() +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::MaxInclusive, this); + + validateElement(XsdTagScope::MaxInclusiveFacet); + + const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet()); + facet->setType(XsdFacet::MaximumInclusive); + + // parse attributes + if (hasAttribute(QString::fromLatin1("fixed"))) { + const QString value = readAttribute(QString::fromLatin1("fixed")); + const Boolean::Ptr fixed = Boolean::fromLexical(value); + if (fixed->hasError()) { + attributeContentError("fixed", "maxInclusive", value, BuiltinTypes::xsBoolean); + return facet; + } + + facet->setFixed(fixed->as()->value()); + } else { + facet->setFixed(false); // the default value + } + + // as maxInclusive can have a value of type anySimpleType, we just read + // the string here and store it for later intepretation + const QString value = readAttribute(QString::fromLatin1("value")); + DerivedString::Ptr string = DerivedString::fromLexical(m_namePool, value); + if (string->hasError()) { + attributeContentError("value", "maxInclusive", value, BuiltinTypes::xsAnySimpleType); + return facet; + } else { + facet->setValue(string); + } + + validateIdAttribute("maxInclusive"); + + TagValidationHandler tagValidator(XsdTagScope::MaxInclusiveFacet, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + facet->addAnnotation(annotation); + } else { + parseUnknown(); + } + } + } + + tagValidator.finalize(); + + return facet; +} + +XsdFacet::Ptr XsdSchemaParser::parseTotalDigitsFacet() +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::TotalDigits, this); + + validateElement(XsdTagScope::TotalDigitsFacet); + + const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet()); + facet->setType(XsdFacet::TotalDigits); + + // parse attributes + if (hasAttribute(QString::fromLatin1("fixed"))) { + const QString value = readAttribute(QString::fromLatin1("fixed")); + const Boolean::Ptr fixed = Boolean::fromLexical(value); + if (fixed->hasError()) { + attributeContentError("fixed", "totalDigits", value, BuiltinTypes::xsBoolean); + return facet; + } + + facet->setFixed(fixed->as()->value()); + } else { + facet->setFixed(false); // the default value + } + + const QString value = readAttribute(QString::fromLatin1("value")); + DerivedInteger::Ptr integer = DerivedInteger::fromLexical(m_namePool, value); + if (integer->hasError()) { + attributeContentError("value", "totalDigits", value, BuiltinTypes::xsPositiveInteger); + return facet; + } else { + facet->setValue(integer); + } + + validateIdAttribute("totalDigits"); + + TagValidationHandler tagValidator(XsdTagScope::TotalDigitsFacet, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + facet->addAnnotation(annotation); + } else { + parseUnknown(); + } + } + } + + tagValidator.finalize(); + + return facet; +} + +XsdFacet::Ptr XsdSchemaParser::parseFractionDigitsFacet() +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::FractionDigits, this); + + validateElement(XsdTagScope::FractionDigitsFacet); + + const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet()); + facet->setType(XsdFacet::FractionDigits); + + // parse attributes + if (hasAttribute(QString::fromLatin1("fixed"))) { + const QString value = readAttribute(QString::fromLatin1("fixed")); + const Boolean::Ptr fixed = Boolean::fromLexical(value); + if (fixed->hasError()) { + attributeContentError("fixed", "fractionDigits", value, BuiltinTypes::xsBoolean); + return facet; + } + + facet->setFixed(fixed->as()->value()); + } else { + facet->setFixed(false); // the default value + } + + const QString value = readAttribute(QString::fromLatin1("value")); + DerivedInteger::Ptr integer = DerivedInteger::fromLexical(m_namePool, value); + if (integer->hasError()) { + attributeContentError("value", "fractionDigits", value, BuiltinTypes::xsNonNegativeInteger); + return facet; + } else { + facet->setValue(integer); + } + + validateIdAttribute("fractionDigits"); + + TagValidationHandler tagValidator(XsdTagScope::FractionDigitsFacet, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + facet->addAnnotation(annotation); + } else { + parseUnknown(); + } + } + } + + tagValidator.finalize(); + + return facet; +} + +XsdFacet::Ptr XsdSchemaParser::parseLengthFacet() +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Length, this); + + validateElement(XsdTagScope::LengthFacet); + + const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet()); + facet->setType(XsdFacet::Length); + + // parse attributes + if (hasAttribute(QString::fromLatin1("fixed"))) { + const QString value = readAttribute(QString::fromLatin1("fixed")); + const Boolean::Ptr fixed = Boolean::fromLexical(value); + if (fixed->hasError()) { + attributeContentError("fixed", "length", value, BuiltinTypes::xsBoolean); + return facet; + } + + facet->setFixed(fixed->as()->value()); + } else { + facet->setFixed(false); // the default value + } + + const QString value = readAttribute(QString::fromLatin1("value")); + DerivedInteger::Ptr integer = DerivedInteger::fromLexical(m_namePool, value); + if (integer->hasError()) { + attributeContentError("value", "length", value, BuiltinTypes::xsNonNegativeInteger); + return facet; + } else { + facet->setValue(integer); + } + + validateIdAttribute("length"); + + TagValidationHandler tagValidator(XsdTagScope::LengthFacet, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + facet->addAnnotation(annotation); + } else { + parseUnknown(); + } + } + } + + tagValidator.finalize(); + + return facet; +} + +XsdFacet::Ptr XsdSchemaParser::parseMinLengthFacet() +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::MinLength, this); + + validateElement(XsdTagScope::MinLengthFacet); + + const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet()); + facet->setType(XsdFacet::MinimumLength); + + // parse attributes + if (hasAttribute(QString::fromLatin1("fixed"))) { + const QString value = readAttribute(QString::fromLatin1("fixed")); + const Boolean::Ptr fixed = Boolean::fromLexical(value); + if (fixed->hasError()) { + attributeContentError("fixed", "minLength", value, BuiltinTypes::xsBoolean); + return facet; + } + + facet->setFixed(fixed->as()->value()); + } else { + facet->setFixed(false); // the default value + } + + const QString value = readAttribute(QString::fromLatin1("value")); + DerivedInteger::Ptr integer = DerivedInteger::fromLexical(m_namePool, value); + if (integer->hasError()) { + attributeContentError("value", "minLength", value, BuiltinTypes::xsNonNegativeInteger); + return facet; + } else { + facet->setValue(integer); + } + + validateIdAttribute("minLength"); + + TagValidationHandler tagValidator(XsdTagScope::MinLengthFacet, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + facet->addAnnotation(annotation); + } else { + parseUnknown(); + } + } + } + + tagValidator.finalize(); + + return facet; +} + +XsdFacet::Ptr XsdSchemaParser::parseMaxLengthFacet() +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::MaxLength, this); + + validateElement(XsdTagScope::MaxLengthFacet); + + const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet()); + facet->setType(XsdFacet::MaximumLength); + + // parse attributes + if (hasAttribute(QString::fromLatin1("fixed"))) { + const QString value = readAttribute(QString::fromLatin1("fixed")); + const Boolean::Ptr fixed = Boolean::fromLexical(value); + if (fixed->hasError()) { + attributeContentError("fixed", "maxLength", value, BuiltinTypes::xsBoolean); + return facet; + } + + facet->setFixed(fixed->as()->value()); + } else { + facet->setFixed(false); // the default value + } + + const QString value = readAttribute(QString::fromLatin1("value")); + DerivedInteger::Ptr integer = DerivedInteger::fromLexical(m_namePool, value); + if (integer->hasError()) { + attributeContentError("value", "maxLength", value, BuiltinTypes::xsNonNegativeInteger); + return facet; + } else { + facet->setValue(integer); + } + + validateIdAttribute("maxLength"); + + TagValidationHandler tagValidator(XsdTagScope::MaxLengthFacet, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + facet->addAnnotation(annotation); + } else { + parseUnknown(); + } + } + } + + tagValidator.finalize(); + + return facet; +} + +XsdFacet::Ptr XsdSchemaParser::parseEnumerationFacet() +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Enumeration, this); + + validateElement(XsdTagScope::EnumerationFacet); + + const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet()); + facet->setType(XsdFacet::Enumeration); + + // parse attributes + facet->setFixed(false); // not defined in schema, but can't hurt + + const QString value = readAttribute(QString::fromLatin1("value")); + + // as enumeration can have a value of type anySimpleType, we just read + // the string here and store it for later intepretation + DerivedString::Ptr string = DerivedString::fromLexical(m_namePool, value); + if (string->hasError()) { + attributeContentError("value", "enumeration", value); + return facet; + } else { + AtomicValue::List multiValue; + multiValue << string; + facet->setMultiValue(multiValue); + } + m_schemaResolver->addEnumerationFacetValue(string, m_namespaceSupport); + + validateIdAttribute("enumeration"); + + TagValidationHandler tagValidator(XsdTagScope::EnumerationFacet, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + facet->addAnnotation(annotation); + } else { + parseUnknown(); + } + } + } + + tagValidator.finalize(); + + return facet; +} + +XsdFacet::Ptr XsdSchemaParser::parseWhiteSpaceFacet() +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::WhiteSpace, this); + + validateElement(XsdTagScope::WhiteSpaceFacet); + + const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet()); + facet->setType(XsdFacet::WhiteSpace); + + // parse attributes + if (hasAttribute(QString::fromLatin1("fixed"))) { + const QString value = readAttribute(QString::fromLatin1("fixed")); + const Boolean::Ptr fixed = Boolean::fromLexical(value); + if (fixed->hasError()) { + attributeContentError("fixed", "whiteSpace", value, BuiltinTypes::xsBoolean); + return facet; + } + + facet->setFixed(fixed->as()->value()); + } else { + facet->setFixed(false); // the default value + } + + const QString value = readAttribute(QString::fromLatin1("value")); + if (value != XsdSchemaToken::toString(XsdSchemaToken::Collapse) && + value != XsdSchemaToken::toString(XsdSchemaToken::Preserve) && + value != XsdSchemaToken::toString(XsdSchemaToken::Replace)) { + attributeContentError("value", "whiteSpace", value); + return facet; + } else { + DerivedString::Ptr string = DerivedString::fromLexical(m_namePool, value); + if (string->hasError()) { + attributeContentError("value", "whiteSpace", value); + return facet; + } else { + facet->setValue(string); + } + } + + validateIdAttribute("whiteSpace"); + + TagValidationHandler tagValidator(XsdTagScope::WhiteSpaceFacet, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + facet->addAnnotation(annotation); + } else { + parseUnknown(); + } + } + } + + tagValidator.finalize(); + + return facet; +} + +XsdFacet::Ptr XsdSchemaParser::parsePatternFacet() +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Pattern, this); + + validateElement(XsdTagScope::PatternFacet); + + const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet()); + facet->setType(XsdFacet::Pattern); + + // parse attributes + + // as pattern can have a value of type anySimpleType, we just read + // the string here and store it for later intepretation + const QString value = readAttribute(QString::fromLatin1("value")); + DerivedString::Ptr string = DerivedString::fromLexical(m_namePool, value); + if (string->hasError()) { + attributeContentError("value", "pattern", value); + return facet; + } else { + AtomicValue::List multiValue; + multiValue << string; + facet->setMultiValue(multiValue); + } + + validateIdAttribute("pattern"); + + TagValidationHandler tagValidator(XsdTagScope::PatternFacet, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + facet->addAnnotation(annotation); + } else { + parseUnknown(); + } + } + } + + tagValidator.finalize(); + + return facet; +} + +XsdFacet::Ptr XsdSchemaParser::parseAssertionFacet() +{ + // this is just a wrapper function around the parseAssertion() method + + const XsdAssertion::Ptr assertion = parseAssertion(XsdSchemaToken::Assertion, XsdTagScope::Assertion); + + const XsdFacet::Ptr facet = XsdFacet::Ptr(new XsdFacet()); + facet->setType(XsdFacet::Assertion); + facet->setAssertions(XsdAssertion::List() << assertion); + + return facet; +} + +XsdComplexType::Ptr XsdSchemaParser::parseGlobalComplexType() +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::ComplexType, this); + + validateElement(XsdTagScope::GlobalComplexType); + + bool hasTypeSpecified = false; + bool hasComplexContent = false; + + const XsdComplexType::Ptr complexType(new XsdComplexType()); + + // parse attributes + if (hasAttribute(QString::fromLatin1("abstract"))) { + const QString abstract = readAttribute(QString::fromLatin1("abstract")); + + const Boolean::Ptr value = Boolean::fromLexical(abstract); + if (value->hasError()) { + attributeContentError("abstract", "complexType", abstract, BuiltinTypes::xsBoolean); + return complexType; + } + + complexType->setIsAbstract(value->as()->value()); + } else { + complexType->setIsAbstract(false); // default value + } + + complexType->setProhibitedSubstitutions(readBlockingConstraintAttribute(NamedSchemaComponent::ExtensionConstraint | NamedSchemaComponent::RestrictionConstraint, "complexType")); + complexType->setDerivationConstraints(readDerivationConstraintAttribute(SchemaType::ExtensionConstraint | SchemaType::RestrictionConstraint, "complexType")); + + const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("complexType")); + complexType->setName(objectName); + + bool effectiveMixed = false; + if (hasAttribute(QString::fromLatin1("mixed"))) { + const QString mixed = readAttribute(QString::fromLatin1("mixed")); + + const Boolean::Ptr value = Boolean::fromLexical(mixed); + if (value->hasError()) { + attributeContentError("mixed", "complexType", mixed, BuiltinTypes::xsBoolean); + return complexType; + } + + effectiveMixed = value->as()->value(); + } + + validateIdAttribute("complexType"); + + TagValidationHandler tagValidator(XsdTagScope::GlobalComplexType, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + complexType->addAnnotation(annotation); + } else if (isSchemaTag(XsdSchemaToken::SimpleContent, token, namespaceToken)) { + if (effectiveMixed) { + error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute") + .arg(formatElement("complexType")) + .arg(formatElement("simpleContent")) + .arg(formatAttribute("mixed"))); + return complexType; + } + + parseSimpleContent(complexType); + hasTypeSpecified = true; + } else if (isSchemaTag(XsdSchemaToken::ComplexContent, token, namespaceToken)) { + bool mixed; + parseComplexContent(complexType, &mixed); + hasTypeSpecified = true; + + effectiveMixed = (effectiveMixed || mixed); + hasComplexContent = true; + } else if (isSchemaTag(XsdSchemaToken::OpenContent, token, namespaceToken)) { + const XsdComplexType::OpenContent::Ptr openContent = parseOpenContent(); + complexType->contentType()->setOpenContent(openContent); + hasComplexContent = true; + } else if (isSchemaTag(XsdSchemaToken::Group, token, namespaceToken)) { + const XsdParticle::Ptr particle(new XsdParticle()); + const XsdTerm::Ptr term = parseReferredGroup(particle); + particle->setTerm(term); + complexType->contentType()->setParticle(particle); + + complexType->setWxsSuperType(BuiltinTypes::xsAnyType); + complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly); + complexType->setDerivationMethod(XsdComplexType::DerivationRestriction); + hasComplexContent = true; + } else if (isSchemaTag(XsdSchemaToken::All, token, namespaceToken)) { + const XsdParticle::Ptr particle(new XsdParticle()); + const XsdTerm::Ptr term = parseLocalAll(particle, complexType); + particle->setTerm(term); + complexType->contentType()->setParticle(particle); + + complexType->setWxsSuperType(BuiltinTypes::xsAnyType); + complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly); + complexType->setDerivationMethod(XsdComplexType::DerivationRestriction); + hasComplexContent = true; + } else if (isSchemaTag(XsdSchemaToken::Choice, token, namespaceToken)) { + const XsdParticle::Ptr particle(new XsdParticle()); + const XsdTerm::Ptr term = parseLocalChoice(particle, complexType); + particle->setTerm(term); + complexType->contentType()->setParticle(particle); + + complexType->setWxsSuperType(BuiltinTypes::xsAnyType); + complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly); + complexType->setDerivationMethod(XsdComplexType::DerivationRestriction); + hasComplexContent = true; + } else if (isSchemaTag(XsdSchemaToken::Sequence, token, namespaceToken)) { + const XsdParticle::Ptr particle(new XsdParticle()); + const XsdTerm::Ptr term = parseLocalSequence(particle, complexType); + particle->setTerm(term); + complexType->contentType()->setParticle(particle); + + complexType->setWxsSuperType(BuiltinTypes::xsAnyType); + complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly); + complexType->setDerivationMethod(XsdComplexType::DerivationRestriction); + hasComplexContent = true; + } else if (isSchemaTag(XsdSchemaToken::Attribute, token, namespaceToken)) { + const XsdAttributeUse::Ptr attributeUse = parseLocalAttribute(complexType); + complexType->addAttributeUse(attributeUse); + + complexType->setWxsSuperType(BuiltinTypes::xsAnyType); + complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly); + complexType->setDerivationMethod(XsdComplexType::DerivationRestriction); + hasComplexContent = true; + } else if (isSchemaTag(XsdSchemaToken::AttributeGroup, token, namespaceToken)) { + const XsdAttributeUse::Ptr attributeUse = parseReferredAttributeGroup(); + complexType->addAttributeUse(attributeUse); + + complexType->setWxsSuperType(BuiltinTypes::xsAnyType); + complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly); + complexType->setDerivationMethod(XsdComplexType::DerivationRestriction); + hasComplexContent = true; + } else if (isSchemaTag(XsdSchemaToken::AnyAttribute, token, namespaceToken)) { + const XsdWildcard::Ptr wildcard = parseAnyAttribute(); + complexType->setAttributeWildcard(wildcard); + + complexType->setWxsSuperType(BuiltinTypes::xsAnyType); + complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly); + complexType->setDerivationMethod(XsdComplexType::DerivationRestriction); + hasComplexContent = true; + } else if (isSchemaTag(XsdSchemaToken::Assert, token, namespaceToken)) { + const XsdAssertion::Ptr assertion = parseAssertion(XsdSchemaToken::Assert, XsdTagScope::Assert); + complexType->addAssertion(assertion); + } else { + parseUnknown(); + } + } + } + + tagValidator.finalize(); + + if (!hasTypeSpecified) { + complexType->setWxsSuperType(BuiltinTypes::xsAnyType); + complexType->setDerivationMethod(XsdComplexType::DerivationRestriction); + hasComplexContent = true; + } + + if (hasComplexContent == true) { + resolveComplexContentType(complexType, effectiveMixed); + } + + return complexType; +} + +XsdComplexType::Ptr XsdSchemaParser::parseLocalComplexType() +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::ComplexType, this); + + validateElement(XsdTagScope::LocalComplexType); + + bool hasTypeSpecified = false; + bool hasComplexContent = true; + + const XsdComplexType::Ptr complexType(new XsdComplexType()); + complexType->setName(m_parserContext->createAnonymousName(m_targetNamespace)); + + // parse attributes + bool effectiveMixed = false; + if (hasAttribute(QString::fromLatin1("mixed"))) { + const QString mixed = readAttribute(QString::fromLatin1("mixed")); + + const Boolean::Ptr value = Boolean::fromLexical(mixed); + if (value->hasError()) { + attributeContentError("mixed", "complexType", mixed, BuiltinTypes::xsBoolean); + return complexType; + } + + effectiveMixed = value->as()->value(); + } + + validateIdAttribute("complexType"); + + TagValidationHandler tagValidator(XsdTagScope::LocalComplexType, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + complexType->addAnnotation(annotation); + } else if (isSchemaTag(XsdSchemaToken::SimpleContent, token, namespaceToken)) { + parseSimpleContent(complexType); + hasTypeSpecified = true; + } else if (isSchemaTag(XsdSchemaToken::ComplexContent, token, namespaceToken)) { + bool mixed; + parseComplexContent(complexType, &mixed); + hasTypeSpecified = true; + + effectiveMixed = (effectiveMixed || mixed); + hasComplexContent = true; + } else if (isSchemaTag(XsdSchemaToken::OpenContent, token, namespaceToken)) { + const XsdComplexType::OpenContent::Ptr openContent = parseOpenContent(); + complexType->contentType()->setOpenContent(openContent); + hasComplexContent = true; + } else if (isSchemaTag(XsdSchemaToken::Group, token, namespaceToken)) { + const XsdParticle::Ptr particle(new XsdParticle()); + const XsdTerm::Ptr term = parseReferredGroup(particle); + particle->setTerm(term); + complexType->contentType()->setParticle(particle); + + complexType->setWxsSuperType(BuiltinTypes::xsAnyType); + complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly); + complexType->setDerivationMethod(XsdComplexType::DerivationRestriction); + hasComplexContent = true; + } else if (isSchemaTag(XsdSchemaToken::All, token, namespaceToken)) { + const XsdParticle::Ptr particle(new XsdParticle()); + const XsdTerm::Ptr term = parseLocalAll(particle, complexType); + particle->setTerm(term); + complexType->contentType()->setParticle(particle); + + complexType->setWxsSuperType(BuiltinTypes::xsAnyType); + complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly); + complexType->setDerivationMethod(XsdComplexType::DerivationRestriction); + hasComplexContent = true; + } else if (isSchemaTag(XsdSchemaToken::Choice, token, namespaceToken)) { + const XsdParticle::Ptr particle(new XsdParticle()); + const XsdTerm::Ptr term = parseLocalChoice(particle, complexType); + particle->setTerm(term); + complexType->contentType()->setParticle(particle); + + complexType->setWxsSuperType(BuiltinTypes::xsAnyType); + complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly); + complexType->setDerivationMethod(XsdComplexType::DerivationRestriction); + hasComplexContent = true; + } else if (isSchemaTag(XsdSchemaToken::Sequence, token, namespaceToken)) { + const XsdParticle::Ptr particle(new XsdParticle()); + const XsdTerm::Ptr term = parseLocalSequence(particle, complexType); + particle->setTerm(term); + complexType->contentType()->setParticle(particle); + + complexType->setWxsSuperType(BuiltinTypes::xsAnyType); + complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly); + complexType->setDerivationMethod(XsdComplexType::DerivationRestriction); + hasComplexContent = true; + } else if (isSchemaTag(XsdSchemaToken::Attribute, token, namespaceToken)) { + const XsdAttributeUse::Ptr attributeUse = parseLocalAttribute(complexType); + complexType->addAttributeUse(attributeUse); + + complexType->setWxsSuperType(BuiltinTypes::xsAnyType); + complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly); + complexType->setDerivationMethod(XsdComplexType::DerivationRestriction); + hasComplexContent = true; + } else if (isSchemaTag(XsdSchemaToken::AttributeGroup, token, namespaceToken)) { + const XsdAttributeUse::Ptr attributeUse = parseReferredAttributeGroup(); + complexType->addAttributeUse(attributeUse); + + complexType->setWxsSuperType(BuiltinTypes::xsAnyType); + complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly); + complexType->setDerivationMethod(XsdComplexType::DerivationRestriction); + hasComplexContent = true; + } else if (isSchemaTag(XsdSchemaToken::AnyAttribute, token, namespaceToken)) { + const XsdWildcard::Ptr wildcard = parseAnyAttribute(); + complexType->setAttributeWildcard(wildcard); + + complexType->setWxsSuperType(BuiltinTypes::xsAnyType); + complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly); + complexType->setDerivationMethod(XsdComplexType::DerivationRestriction); + hasComplexContent = true; + } else if (isSchemaTag(XsdSchemaToken::Assert, token, namespaceToken)) { + const XsdAssertion::Ptr assertion = parseAssertion(XsdSchemaToken::Assert, XsdTagScope::Assert); + complexType->addAssertion(assertion); + } else { + parseUnknown(); + } + } + } + + tagValidator.finalize(); + + if (!hasTypeSpecified) { + complexType->setWxsSuperType(BuiltinTypes::xsAnyType); + complexType->setDerivationMethod(XsdComplexType::DerivationRestriction); + hasComplexContent = true; + } + + if (hasComplexContent == true) { + resolveComplexContentType(complexType, effectiveMixed); + } + + return complexType; +} + +void XsdSchemaParser::resolveComplexContentType(const XsdComplexType::Ptr &complexType, bool effectiveMixed) +{ + // @see http://www.w3.org/TR/xmlschema11-1/#dcl.ctd.ctcc.common + + // 1 + // the effectiveMixed contains the effective mixed value + + // 2 + bool hasEmptyContent = false; + if (!complexType->contentType()->particle()) { + hasEmptyContent = true; // 2.1.1 + } else { + if (complexType->contentType()->particle()->term()->isModelGroup()) { + const XsdModelGroup::Ptr group = complexType->contentType()->particle()->term(); + if (group->compositor() == XsdModelGroup::SequenceCompositor || group->compositor() == XsdModelGroup::AllCompositor) { + if (group->particles().isEmpty()) + hasEmptyContent = true; // 2.1.2 + } else if (group->compositor() == XsdModelGroup::ChoiceCompositor) { + if ((complexType->contentType()->particle()->minimumOccurs() == 0) && group->particles().isEmpty()) + hasEmptyContent = true; // 2.1.3 + } + + if ((complexType->contentType()->particle()->maximumOccursUnbounded() == false) && (complexType->contentType()->particle()->maximumOccurs() == 0)) + hasEmptyContent = true; // 2.1.4 + } + } + + const XsdParticle::Ptr explicitContent = (hasEmptyContent ? XsdParticle::Ptr() : complexType->contentType()->particle()); + + // do all the other work (3, 4, 5 and 6) in the resolver, as they need access to the base type object + m_schemaResolver->addComplexContentType(complexType, explicitContent, effectiveMixed); +} + +void XsdSchemaParser::parseSimpleContent(const XsdComplexType::Ptr &complexType) +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::SimpleContent, this); + + validateElement(XsdTagScope::SimpleContent); + + complexType->contentType()->setVariety(XsdComplexType::ContentType::Simple); + + // parse attributes + validateIdAttribute("simpleContent"); + + TagValidationHandler tagValidator(XsdTagScope::SimpleContent, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + complexType->addAnnotation(annotation); + } else if (isSchemaTag(XsdSchemaToken::Restriction, token, namespaceToken)) { + parseSimpleContentRestriction(complexType); + } else if (isSchemaTag(XsdSchemaToken::Extension, token, namespaceToken)) { + parseSimpleContentExtension(complexType); + } else { + parseUnknown(); + } + } + } + + tagValidator.finalize(); +} + +void XsdSchemaParser::parseSimpleContentRestriction(const XsdComplexType::Ptr &complexType) +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Restriction, this); + + validateElement(XsdTagScope::SimpleContentRestriction); + + complexType->setDerivationMethod(XsdComplexType::DerivationRestriction); + + // parse attributes + const QString baseType = readQNameAttribute(QString::fromLatin1("base"), "restriction"); + QXmlName typeName; + convertName(baseType, NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName + + validateIdAttribute("restriction"); + + XsdFacet::Hash facets; + QList patternFacets; + QList enumerationFacets; + QList assertionFacets; + + TagValidationHandler tagValidator(XsdTagScope::SimpleContentRestriction, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + complexType->addAnnotation(annotation); + } else if (isSchemaTag(XsdSchemaToken::SimpleType, token, namespaceToken)) { + const XsdSimpleType::Ptr type = parseLocalSimpleType(); + type->setContext(complexType); //TODO: investigate what the schema spec really wants here?!? + complexType->contentType()->setSimpleType(type); + + // add it to list of anonymous types as well + addAnonymousType(type); + } else if (isSchemaTag(XsdSchemaToken::MinExclusive, token, namespaceToken)) { + const XsdFacet::Ptr facet = parseMinExclusiveFacet(); + addFacet(facet, facets, complexType); + } else if (isSchemaTag(XsdSchemaToken::MinInclusive, token, namespaceToken)) { + const XsdFacet::Ptr facet = parseMinInclusiveFacet(); + addFacet(facet, facets, complexType); + } else if (isSchemaTag(XsdSchemaToken::MaxExclusive, token, namespaceToken)) { + const XsdFacet::Ptr facet = parseMaxExclusiveFacet(); + addFacet(facet, facets, complexType); + } else if (isSchemaTag(XsdSchemaToken::MaxInclusive, token, namespaceToken)) { + const XsdFacet::Ptr facet = parseMaxInclusiveFacet(); + addFacet(facet, facets, complexType); + } else if (isSchemaTag(XsdSchemaToken::TotalDigits, token, namespaceToken)) { + const XsdFacet::Ptr facet = parseTotalDigitsFacet(); + addFacet(facet, facets, complexType); + } else if (isSchemaTag(XsdSchemaToken::FractionDigits, token, namespaceToken)) { + const XsdFacet::Ptr facet = parseFractionDigitsFacet(); + addFacet(facet, facets, complexType); + } else if (isSchemaTag(XsdSchemaToken::Length, token, namespaceToken)) { + const XsdFacet::Ptr facet = parseLengthFacet(); + addFacet(facet, facets, complexType); + } else if (isSchemaTag(XsdSchemaToken::MinLength, token, namespaceToken)) { + const XsdFacet::Ptr facet = parseMinLengthFacet(); + addFacet(facet, facets, complexType); + } else if (isSchemaTag(XsdSchemaToken::MaxLength, token, namespaceToken)) { + const XsdFacet::Ptr facet = parseMaxLengthFacet(); + addFacet(facet, facets, complexType); + } else if (isSchemaTag(XsdSchemaToken::Enumeration, token, namespaceToken)) { + const XsdFacet::Ptr facet = parseEnumerationFacet(); + enumerationFacets.append(facet); + } else if (isSchemaTag(XsdSchemaToken::WhiteSpace, token, namespaceToken)) { + const XsdFacet::Ptr facet = parseWhiteSpaceFacet(); + addFacet(facet, facets, complexType); + } else if (isSchemaTag(XsdSchemaToken::Pattern, token, namespaceToken)) { + const XsdFacet::Ptr facet = parsePatternFacet(); + patternFacets.append(facet); + } else if (isSchemaTag(XsdSchemaToken::Assertion, token, namespaceToken)) { + const XsdFacet::Ptr facet = parseAssertionFacet(); + assertionFacets.append(facet); + } else if (isSchemaTag(XsdSchemaToken::Attribute, token, namespaceToken)) { + const XsdAttributeUse::Ptr attributeUse = parseLocalAttribute(complexType); + complexType->addAttributeUse(attributeUse); + } else if (isSchemaTag(XsdSchemaToken::AttributeGroup, token, namespaceToken)) { + const XsdAttributeUse::Ptr attributeUse = parseReferredAttributeGroup(); + complexType->addAttributeUse(attributeUse); + } else if (isSchemaTag(XsdSchemaToken::AnyAttribute, token, namespaceToken)) { + const XsdWildcard::Ptr wildcard = parseAnyAttribute(); + complexType->setAttributeWildcard(wildcard); + } else if (isSchemaTag(XsdSchemaToken::Assert, token, namespaceToken)) { + const XsdAssertion::Ptr assertion = parseAssertion(XsdSchemaToken::Assert, XsdTagScope::Assert); + complexType->addAssertion(assertion); + } else { + parseUnknown(); + } + } + } + + tagValidator.finalize(); + + // merge all pattern facets into one multi value facet + if (!patternFacets.isEmpty()) { + const XsdFacet::Ptr patternFacet(new XsdFacet()); + patternFacet->setType(XsdFacet::Pattern); + + AtomicValue::List multiValue; + for (int i = 0; i < patternFacets.count(); ++i) + multiValue << patternFacets.at(i)->multiValue(); + + patternFacet->setMultiValue(multiValue); + addFacet(patternFacet, facets, complexType); + } + + // merge all enumeration facets into one multi value facet + if (!enumerationFacets.isEmpty()) { + const XsdFacet::Ptr enumerationFacet(new XsdFacet()); + enumerationFacet->setType(XsdFacet::Enumeration); + + AtomicValue::List multiValue; + for (int i = 0; i < enumerationFacets.count(); ++i) + multiValue << enumerationFacets.at(i)->multiValue(); + + enumerationFacet->setMultiValue(multiValue); + addFacet(enumerationFacet, facets, complexType); + } + + // merge all assertion facets into one facet + if (!assertionFacets.isEmpty()) { + const XsdFacet::Ptr assertionFacet(new XsdFacet()); + assertionFacet->setType(XsdFacet::Assertion); + + XsdAssertion::List assertions; + for (int i = 0; i < assertionFacets.count(); ++i) + assertions << assertionFacets.at(i)->assertions(); + + assertionFacet->setAssertions(assertions); + addFacet(assertionFacet, facets, complexType); + } + + m_schemaResolver->addComplexBaseType(complexType, typeName, currentSourceLocation(), facets); // add to resolver +} + +void XsdSchemaParser::parseSimpleContentExtension(const XsdComplexType::Ptr &complexType) +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Extension, this); + + validateElement(XsdTagScope::SimpleContentExtension); + + complexType->setDerivationMethod(XsdComplexType::DerivationExtension); + + // parse attributes + const QString baseType = readQNameAttribute(QString::fromLatin1("base"), "extension"); + QXmlName typeName; + convertName(baseType, NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName + m_schemaResolver->addComplexBaseType(complexType, typeName, currentSourceLocation()); // add to resolver + + validateIdAttribute("extension"); + + TagValidationHandler tagValidator(XsdTagScope::SimpleContentExtension, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + complexType->addAnnotation(annotation); + } else if (isSchemaTag(XsdSchemaToken::Attribute, token, namespaceToken)) { + const XsdAttributeUse::Ptr attributeUse = parseLocalAttribute(complexType); + complexType->addAttributeUse(attributeUse); + } else if (isSchemaTag(XsdSchemaToken::AttributeGroup, token, namespaceToken)) { + const XsdAttributeUse::Ptr attributeUse = parseReferredAttributeGroup(); + complexType->addAttributeUse(attributeUse); + } else if (isSchemaTag(XsdSchemaToken::AnyAttribute, token, namespaceToken)) { + const XsdWildcard::Ptr wildcard = parseAnyAttribute(); + complexType->setAttributeWildcard(wildcard); + } else if (isSchemaTag(XsdSchemaToken::Assert, token, namespaceToken)) { + const XsdAssertion::Ptr assertion = parseAssertion(XsdSchemaToken::Assert, XsdTagScope::Assert); + complexType->addAssertion(assertion); + } else { + parseUnknown(); + } + } + } + + tagValidator.finalize(); +} + +void XsdSchemaParser::parseComplexContent(const XsdComplexType::Ptr &complexType, bool *mixed) +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::ComplexContent, this); + + validateElement(XsdTagScope::ComplexContent); + + complexType->contentType()->setVariety(XsdComplexType::ContentType::ElementOnly); + + // parse attributes + if (hasAttribute(QString::fromLatin1("mixed"))) { + const QString mixedStr = readAttribute(QString::fromLatin1("mixed")); + + const Boolean::Ptr value = Boolean::fromLexical(mixedStr); + if (value->hasError()) { + attributeContentError("mixed", "complexType", mixedStr, BuiltinTypes::xsBoolean); + return; + } + + *mixed = value->as()->value(); + } else { + *mixed = false; + } + + validateIdAttribute("complexContent"); + + TagValidationHandler tagValidator(XsdTagScope::ComplexContent, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + complexType->addAnnotation(annotation); + } else if (isSchemaTag(XsdSchemaToken::Restriction, token, namespaceToken)) { + parseComplexContentRestriction(complexType); + } else if (isSchemaTag(XsdSchemaToken::Extension, token, namespaceToken)) { + parseComplexContentExtension(complexType); + } else { + parseUnknown(); + } + } + } + + tagValidator.finalize(); +} + +void XsdSchemaParser::parseComplexContentRestriction(const XsdComplexType::Ptr &complexType) +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Restriction, this); + + validateElement(XsdTagScope::ComplexContentRestriction); + + complexType->setDerivationMethod(XsdComplexType::DerivationRestriction); + + // parse attributes + const QString baseType = readQNameAttribute(QString::fromLatin1("base"), "restriction"); + QXmlName typeName; + convertName(baseType, NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName + m_schemaResolver->addComplexBaseType(complexType, typeName, currentSourceLocation()); // add to resolver + + validateIdAttribute("restriction"); + + TagValidationHandler tagValidator(XsdTagScope::ComplexContentRestriction, this, m_namePool); + + bool hasContent = false; + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + complexType->addAnnotation(annotation); + } else if (isSchemaTag(XsdSchemaToken::OpenContent, token, namespaceToken)) { + const XsdComplexType::OpenContent::Ptr openContent = parseOpenContent(); + complexType->contentType()->setOpenContent(openContent); + hasContent = true; + } else if (isSchemaTag(XsdSchemaToken::Group, token, namespaceToken)) { + const XsdParticle::Ptr particle(new XsdParticle()); + const XsdTerm::Ptr term = parseReferredGroup(particle); + particle->setTerm(term); + complexType->contentType()->setParticle(particle); + hasContent = true; + } else if (isSchemaTag(XsdSchemaToken::All, token, namespaceToken)) { + const XsdParticle::Ptr particle(new XsdParticle()); + const XsdTerm::Ptr term = parseLocalAll(particle, complexType); + particle->setTerm(term); + complexType->contentType()->setParticle(particle); + hasContent = true; + } else if (isSchemaTag(XsdSchemaToken::Choice, token, namespaceToken)) { + const XsdParticle::Ptr particle(new XsdParticle()); + const XsdTerm::Ptr term = parseLocalChoice(particle, complexType); + particle->setTerm(term); + complexType->contentType()->setParticle(particle); + hasContent = true; + } else if (isSchemaTag(XsdSchemaToken::Sequence, token, namespaceToken)) { + const XsdParticle::Ptr particle(new XsdParticle()); + const XsdTerm::Ptr term = parseLocalSequence(particle, complexType); + particle->setTerm(term); + complexType->contentType()->setParticle(particle); + hasContent = true; + } else if (isSchemaTag(XsdSchemaToken::Attribute, token, namespaceToken)) { + const XsdAttributeUse::Ptr attributeUse = parseLocalAttribute(complexType); + complexType->addAttributeUse(attributeUse); + } else if (isSchemaTag(XsdSchemaToken::AttributeGroup, token, namespaceToken)) { + const XsdAttributeUse::Ptr attributeUse = parseReferredAttributeGroup(); + complexType->addAttributeUse(attributeUse); + } else if (isSchemaTag(XsdSchemaToken::AnyAttribute, token, namespaceToken)) { + const XsdWildcard::Ptr wildcard = parseAnyAttribute(); + complexType->setAttributeWildcard(wildcard); + } else if (isSchemaTag(XsdSchemaToken::Assert, token, namespaceToken)) { + const XsdAssertion::Ptr assertion = parseAssertion(XsdSchemaToken::Assert, XsdTagScope::Assert); + complexType->addAssertion(assertion); + } else { + parseUnknown(); + } + } + } + + if (!hasContent) + complexType->contentType()->setVariety(XsdComplexType::ContentType::Empty); + + tagValidator.finalize(); +} + +void XsdSchemaParser::parseComplexContentExtension(const XsdComplexType::Ptr &complexType) +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Extension, this); + + validateElement(XsdTagScope::ComplexContentExtension); + + complexType->setDerivationMethod(XsdComplexType::DerivationExtension); + + // parse attributes + const QString baseType = readQNameAttribute(QString::fromLatin1("base"), "extension"); + QXmlName typeName; + convertName(baseType, NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName + m_schemaResolver->addComplexBaseType(complexType, typeName, currentSourceLocation()); // add to resolver + + validateIdAttribute("extension"); + + TagValidationHandler tagValidator(XsdTagScope::ComplexContentExtension, this, m_namePool); + + bool hasContent = false; + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + complexType->addAnnotation(annotation); + } else if (isSchemaTag(XsdSchemaToken::OpenContent, token, namespaceToken)) { + const XsdComplexType::OpenContent::Ptr openContent = parseOpenContent(); + complexType->contentType()->setOpenContent(openContent); + hasContent = true; + } else if (isSchemaTag(XsdSchemaToken::Group, token, namespaceToken)) { + const XsdParticle::Ptr particle(new XsdParticle()); + const XsdTerm::Ptr term = parseReferredGroup(particle); + particle->setTerm(term); + complexType->contentType()->setParticle(particle); + hasContent = true; + } else if (isSchemaTag(XsdSchemaToken::All, token, namespaceToken)) { + const XsdParticle::Ptr particle(new XsdParticle()); + const XsdTerm::Ptr term = parseLocalAll(particle, complexType); + particle->setTerm(term); + complexType->contentType()->setParticle(particle); + hasContent = true; + } else if (isSchemaTag(XsdSchemaToken::Choice, token, namespaceToken)) { + const XsdParticle::Ptr particle(new XsdParticle()); + const XsdTerm::Ptr term = parseLocalChoice(particle, complexType); + particle->setTerm(term); + complexType->contentType()->setParticle(particle); + hasContent = true; + } else if (isSchemaTag(XsdSchemaToken::Sequence, token, namespaceToken)) { + const XsdParticle::Ptr particle(new XsdParticle()); + const XsdTerm::Ptr term = parseLocalSequence(particle, complexType); + particle->setTerm(term); + complexType->contentType()->setParticle(particle); + hasContent = true; + } else if (isSchemaTag(XsdSchemaToken::Attribute, token, namespaceToken)) { + const XsdAttributeUse::Ptr attributeUse = parseLocalAttribute(complexType); + complexType->addAttributeUse(attributeUse); + } else if (isSchemaTag(XsdSchemaToken::AttributeGroup, token, namespaceToken)) { + const XsdAttributeUse::Ptr attributeUse = parseReferredAttributeGroup(); + complexType->addAttributeUse(attributeUse); + } else if (isSchemaTag(XsdSchemaToken::AnyAttribute, token, namespaceToken)) { + const XsdWildcard::Ptr wildcard = parseAnyAttribute(); + complexType->setAttributeWildcard(wildcard); + } else if (isSchemaTag(XsdSchemaToken::Assert, token, namespaceToken)) { + const XsdAssertion::Ptr assertion = parseAssertion(XsdSchemaToken::Assert, XsdTagScope::Assert); + complexType->addAssertion(assertion); + } else { + parseUnknown(); + } + } + } + + if (!hasContent) + complexType->contentType()->setVariety(XsdComplexType::ContentType::Empty); + + tagValidator.finalize(); +} + + +XsdAssertion::Ptr XsdSchemaParser::parseAssertion(const XsdSchemaToken::NodeName &nodeName, const XsdTagScope::Type &tag) +{ + const ElementNamespaceHandler namespaceHandler(nodeName, this); + + validateElement(tag); + + const XsdAssertion::Ptr assertion(new XsdAssertion()); + + // parse attributes + + const XsdXPathExpression::Ptr expression = readXPathExpression("assertion"); + assertion->setTest(expression); + + const QString test = readXPathAttribute(QString::fromLatin1("test"), XPath20, "assertion"); + expression->setExpression(test); + + validateIdAttribute("assertion"); + + TagValidationHandler tagValidator(tag, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + assertion->addAnnotation(annotation); + } else { + parseUnknown(); + } + } + } + + tagValidator.finalize(); + + return assertion; +} + +XsdComplexType::OpenContent::Ptr XsdSchemaParser::parseOpenContent() +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::OpenContent, this); + + validateElement(XsdTagScope::OpenContent); + + const XsdComplexType::OpenContent::Ptr openContent(new XsdComplexType::OpenContent()); + + if (hasAttribute(QString::fromLatin1("mode"))) { + const QString mode = readAttribute(QString::fromLatin1("mode")); + + if (mode == QString::fromLatin1("none")) { + m_defaultOpenContent->setMode(XsdComplexType::OpenContent::None); + } else if (mode == QString::fromLatin1("interleave")) { + m_defaultOpenContent->setMode(XsdComplexType::OpenContent::Interleave); + } else if (mode == QString::fromLatin1("suffix")) { + m_defaultOpenContent->setMode(XsdComplexType::OpenContent::Suffix); + } else { + attributeContentError("mode", "openContent", mode); + return openContent; + } + } else { + openContent->setMode(XsdComplexType::OpenContent::Interleave); + } + + validateIdAttribute("openContent"); + + TagValidationHandler tagValidator(XsdTagScope::OpenContent, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + openContent->addAnnotation(annotation); + } else if (isSchemaTag(XsdSchemaToken::Any, token, namespaceToken)) { + const XsdParticle::Ptr particle; + const XsdWildcard::Ptr wildcard = parseAny(particle); + openContent->setWildcard(wildcard); + } else { + parseUnknown(); + } + } + } + + tagValidator.finalize(); + + return openContent; +} + +XsdModelGroup::Ptr XsdSchemaParser::parseNamedGroup() +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Group, this); + + validateElement(XsdTagScope::NamedGroup); + + const XsdModelGroup::Ptr modelGroup(new XsdModelGroup()); + XsdModelGroup::Ptr group; + + QXmlName objectName; + if (hasAttribute(QString::fromLatin1("name"))) { + objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("group")); + } + + validateIdAttribute("group"); + + TagValidationHandler tagValidator(XsdTagScope::NamedGroup, this, m_namePool); + + XsdAnnotation::Ptr annotation; + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + annotation = parseAnnotation(); + } else if (isSchemaTag(XsdSchemaToken::All, token, namespaceToken)) { + group = parseAll(modelGroup); + } else if (isSchemaTag(XsdSchemaToken::Choice, token, namespaceToken)) { + group = parseChoice(modelGroup); + } else if (isSchemaTag(XsdSchemaToken::Sequence, token, namespaceToken)) { + group = parseSequence(modelGroup); + } else { + parseUnknown(); + } + } + } + + tagValidator.finalize(); + + group->setName(objectName); + + if (annotation) + group->addAnnotation(annotation); + + return group; +} + +XsdTerm::Ptr XsdSchemaParser::parseReferredGroup(const XsdParticle::Ptr &particle) +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Group, this); + + validateElement(XsdTagScope::ReferredGroup); + + const XsdReference::Ptr reference(new XsdReference()); + reference->setType(XsdReference::ModelGroup); + reference->setSourceLocation(currentSourceLocation()); + + // parse attributes + if (!parseMinMaxConstraint(particle, "group")) { + return reference; + } + + const QString value = readQNameAttribute(QString::fromLatin1("ref"), "group"); + QXmlName referenceName; + convertName(value, NamespaceSupport::ElementName, referenceName); // translate qualified name into QXmlName + reference->setReferenceName(referenceName); + + validateIdAttribute("group"); + + TagValidationHandler tagValidator(XsdTagScope::ReferredGroup, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + reference->addAnnotation(annotation); + } else { + parseUnknown(); + } + } + } + + tagValidator.finalize(); + + return reference; +} + +XsdModelGroup::Ptr XsdSchemaParser::parseAll(const NamedSchemaComponent::Ptr &parent) +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::All, this); + + validateElement(XsdTagScope::All); + + const XsdModelGroup::Ptr modelGroup(new XsdModelGroup()); + modelGroup->setCompositor(XsdModelGroup::AllCompositor); + + validateIdAttribute("all"); + + TagValidationHandler tagValidator(XsdTagScope::All, this, m_namePool); + + XsdParticle::List particles; + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + modelGroup->addAnnotation(annotation); + } else if (isSchemaTag(XsdSchemaToken::Element, token, namespaceToken)) { + const XsdParticle::Ptr particle(new XsdParticle()); + const XsdTerm::Ptr term = parseLocalElement(particle, parent); + particle->setTerm(term); + + if (particle->maximumOccursUnbounded() || particle->maximumOccurs() > 1) { + error(QtXmlPatterns::tr("%1 attribute of %2 element must be %3 or %4") + .arg(formatAttribute("maxOccurs")) + .arg(formatElement("all")) + .arg(formatData("0")) + .arg(formatData("1"))); + return modelGroup; + } + + particles.append(particle); + } else { + parseUnknown(); + } + } + } + + modelGroup->setParticles(particles); + + tagValidator.finalize(); + + return modelGroup; +} + +XsdModelGroup::Ptr XsdSchemaParser::parseLocalAll(const XsdParticle::Ptr &particle, const NamedSchemaComponent::Ptr &parent) +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::All, this); + + validateElement(XsdTagScope::LocalAll); + + const XsdModelGroup::Ptr modelGroup(new XsdModelGroup()); + modelGroup->setCompositor(XsdModelGroup::AllCompositor); + + // parse attributes + if (!parseMinMaxConstraint(particle, "all")) { + return modelGroup; + } + if (particle->maximumOccursUnbounded() || particle->maximumOccurs() != 1) { + error(QtXmlPatterns::tr("%1 attribute of %2 element must have a value of %3") + .arg(formatAttribute("maxOccurs")) + .arg(formatElement("all")) + .arg(formatData("1"))); + return modelGroup; + } + if (particle->minimumOccurs() != 0 && particle->minimumOccurs() != 1) { + error(QtXmlPatterns::tr("%1 attribute of %2 element must have a value of %3 or %4") + .arg(formatAttribute("minOccurs")) + .arg(formatElement("all")) + .arg(formatData("0")) + .arg(formatData("1"))); + return modelGroup; + } + + validateIdAttribute("all"); + + TagValidationHandler tagValidator(XsdTagScope::LocalAll, this, m_namePool); + + XsdParticle::List particles; + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + modelGroup->addAnnotation(annotation); + } else if (isSchemaTag(XsdSchemaToken::Element, token, namespaceToken)) { + const XsdParticle::Ptr particle(new XsdParticle()); + const XsdTerm::Ptr term = parseLocalElement(particle, parent); + particle->setTerm(term); + + if (particle->maximumOccursUnbounded() || particle->maximumOccurs() > 1) { + error(QtXmlPatterns::tr("%1 attribute of %2 element must have a value of %3 or %4") + .arg(formatAttribute("maxOccurs")) + .arg(formatElement("all")) + .arg(formatData("0")) + .arg(formatData("1"))); + return modelGroup; + } + + particles.append(particle); + } else { + parseUnknown(); + } + } + } + + modelGroup->setParticles(particles); + + tagValidator.finalize(); + + return modelGroup; +} + +XsdModelGroup::Ptr XsdSchemaParser::parseChoice(const NamedSchemaComponent::Ptr &parent) +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Choice, this); + + validateElement(XsdTagScope::Choice); + + const XsdModelGroup::Ptr modelGroup(new XsdModelGroup()); + modelGroup->setCompositor(XsdModelGroup::ChoiceCompositor); + + validateIdAttribute("choice"); + + XsdParticle::List particles; + + TagValidationHandler tagValidator(XsdTagScope::Choice, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + modelGroup->addAnnotation(annotation); + } else if (isSchemaTag(XsdSchemaToken::Element, token, namespaceToken)) { + const XsdParticle::Ptr particle(new XsdParticle()); + const XsdTerm::Ptr term = parseLocalElement(particle, parent); + particle->setTerm(term); + particles.append(particle); + } else if (isSchemaTag(XsdSchemaToken::Group, token, namespaceToken)) { + const XsdParticle::Ptr particle(new XsdParticle()); + const XsdTerm::Ptr term = parseReferredGroup(particle); + m_schemaResolver->addAllGroupCheck(term); + particle->setTerm(term); + particles.append(particle); + } else if (isSchemaTag(XsdSchemaToken::Choice, token, namespaceToken)) { + const XsdParticle::Ptr particle(new XsdParticle()); + const XsdTerm::Ptr term = parseLocalChoice(particle, parent); + particle->setTerm(term); + particles.append(particle); + } else if (isSchemaTag(XsdSchemaToken::Sequence, token, namespaceToken)) { + const XsdParticle::Ptr particle(new XsdParticle()); + const XsdTerm::Ptr term = parseLocalSequence(particle, parent); + particle->setTerm(term); + particles.append(particle); + } else if (isSchemaTag(XsdSchemaToken::Any, token, namespaceToken)) { + const XsdParticle::Ptr particle(new XsdParticle()); + const XsdTerm::Ptr term = parseAny(particle); + particle->setTerm(term); + particles.append(particle); + } else { + parseUnknown(); + } + } + } + + modelGroup->setParticles(particles); + + tagValidator.finalize(); + + return modelGroup; +} + +XsdModelGroup::Ptr XsdSchemaParser::parseLocalChoice(const XsdParticle::Ptr &particle, const NamedSchemaComponent::Ptr &parent) +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Choice, this); + + validateElement(XsdTagScope::LocalChoice); + + const XsdModelGroup::Ptr modelGroup(new XsdModelGroup()); + modelGroup->setCompositor(XsdModelGroup::ChoiceCompositor); + + // parse attributes + if (!parseMinMaxConstraint(particle, "choice")) { + return modelGroup; + } + + validateIdAttribute("choice"); + + XsdParticle::List particles; + + TagValidationHandler tagValidator(XsdTagScope::LocalChoice, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + modelGroup->addAnnotation(annotation); + } else if (isSchemaTag(XsdSchemaToken::Element, token, namespaceToken)) { + const XsdParticle::Ptr particle(new XsdParticle()); + const XsdTerm::Ptr term = parseLocalElement(particle, parent); + particle->setTerm(term); + particles.append(particle); + } else if (isSchemaTag(XsdSchemaToken::Group, token, namespaceToken)) { + const XsdParticle::Ptr particle(new XsdParticle()); + const XsdTerm::Ptr term = parseReferredGroup(particle); + m_schemaResolver->addAllGroupCheck(term); + particle->setTerm(term); + particles.append(particle); + } else if (isSchemaTag(XsdSchemaToken::Choice, token, namespaceToken)) { + const XsdParticle::Ptr particle(new XsdParticle()); + const XsdTerm::Ptr term = parseLocalChoice(particle, parent); + particle->setTerm(term); + particles.append(particle); + } else if (isSchemaTag(XsdSchemaToken::Sequence, token, namespaceToken)) { + const XsdParticle::Ptr particle(new XsdParticle()); + const XsdTerm::Ptr term = parseLocalSequence(particle, parent); + particle->setTerm(term); + particles.append(particle); + } else if (isSchemaTag(XsdSchemaToken::Any, token, namespaceToken)) { + const XsdParticle::Ptr particle(new XsdParticle()); + const XsdTerm::Ptr term = parseAny(particle); + particle->setTerm(term); + particles.append(particle); + } else { + parseUnknown(); + } + } + } + + modelGroup->setParticles(particles); + + tagValidator.finalize(); + + return modelGroup; +} + +XsdModelGroup::Ptr XsdSchemaParser::parseSequence(const NamedSchemaComponent::Ptr &parent) +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Sequence, this); + + validateElement(XsdTagScope::Sequence); + + const XsdModelGroup::Ptr modelGroup(new XsdModelGroup()); + modelGroup->setCompositor(XsdModelGroup::SequenceCompositor); + + validateIdAttribute("sequence"); + + XsdParticle::List particles; + + TagValidationHandler tagValidator(XsdTagScope::Sequence, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + modelGroup->addAnnotation(annotation); + } else if (isSchemaTag(XsdSchemaToken::Element, token, namespaceToken)) { + const XsdParticle::Ptr particle(new XsdParticle()); + const XsdTerm::Ptr term = parseLocalElement(particle, parent); + particle->setTerm(term); + particles.append(particle); + } else if (isSchemaTag(XsdSchemaToken::Group, token, namespaceToken)) { + const XsdParticle::Ptr particle(new XsdParticle()); + const XsdTerm::Ptr term = parseReferredGroup(particle); + m_schemaResolver->addAllGroupCheck(term); + particle->setTerm(term); + particles.append(particle); + } else if (isSchemaTag(XsdSchemaToken::Choice, token, namespaceToken)) { + const XsdParticle::Ptr particle(new XsdParticle()); + const XsdTerm::Ptr term = parseLocalChoice(particle, parent); + particle->setTerm(term); + particles.append(particle); + } else if (isSchemaTag(XsdSchemaToken::Sequence, token, namespaceToken)) { + const XsdParticle::Ptr particle(new XsdParticle()); + const XsdTerm::Ptr term = parseLocalSequence(particle, parent); + particle->setTerm(term); + particles.append(particle); + } else if (isSchemaTag(XsdSchemaToken::Any, token, namespaceToken)) { + const XsdParticle::Ptr particle(new XsdParticle()); + const XsdTerm::Ptr term = parseAny(particle); + particle->setTerm(term); + particles.append(particle); + } else { + parseUnknown(); + } + } + } + + modelGroup->setParticles(particles); + + tagValidator.finalize(); + + return modelGroup; +} + +XsdModelGroup::Ptr XsdSchemaParser::parseLocalSequence(const XsdParticle::Ptr &particle, const NamedSchemaComponent::Ptr &parent) +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Sequence, this); + + validateElement(XsdTagScope::LocalSequence); + + const XsdModelGroup::Ptr modelGroup(new XsdModelGroup()); + modelGroup->setCompositor(XsdModelGroup::SequenceCompositor); + + // parse attributes + if (!parseMinMaxConstraint(particle, "sequence")) { + return modelGroup; + } + + validateIdAttribute("sequence"); + + XsdParticle::List particles; + + TagValidationHandler tagValidator(XsdTagScope::LocalSequence, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + modelGroup->addAnnotation(annotation); + } else if (isSchemaTag(XsdSchemaToken::Element, token, namespaceToken)) { + const XsdParticle::Ptr particle(new XsdParticle()); + const XsdTerm::Ptr term = parseLocalElement(particle, parent); + particle->setTerm(term); + particles.append(particle); + } else if (isSchemaTag(XsdSchemaToken::Group, token, namespaceToken)) { + const XsdParticle::Ptr particle(new XsdParticle()); + const XsdTerm::Ptr term = parseReferredGroup(particle); + m_schemaResolver->addAllGroupCheck(term); + particle->setTerm(term); + particles.append(particle); + } else if (isSchemaTag(XsdSchemaToken::Choice, token, namespaceToken)) { + const XsdParticle::Ptr particle(new XsdParticle()); + const XsdTerm::Ptr term = parseLocalChoice(particle, parent); + particle->setTerm(term); + particles.append(particle); + } else if (isSchemaTag(XsdSchemaToken::Sequence, token, namespaceToken)) { + const XsdParticle::Ptr particle(new XsdParticle()); + const XsdTerm::Ptr term = parseLocalSequence(particle, parent); + particle->setTerm(term); + particles.append(particle); + } else if (isSchemaTag(XsdSchemaToken::Any, token, namespaceToken)) { + const XsdParticle::Ptr particle(new XsdParticle()); + const XsdTerm::Ptr term = parseAny(particle); + particle->setTerm(term); + particles.append(particle); + } else { + parseUnknown(); + } + } + } + + modelGroup->setParticles(particles); + + tagValidator.finalize(); + + return modelGroup; +} + +XsdAttribute::Ptr XsdSchemaParser::parseGlobalAttribute() +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Attribute, this); + + validateElement(XsdTagScope::GlobalAttribute); + + const XsdAttribute::Ptr attribute(new XsdAttribute()); + attribute->setScope(XsdAttribute::Scope::Ptr(new XsdAttribute::Scope())); + attribute->scope()->setVariety(XsdAttribute::Scope::Global); + + if (hasAttribute(QString::fromLatin1("default")) && hasAttribute(QString::fromLatin1("fixed"))) { + error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together") + .arg(formatElement("attribute")) + .arg(formatAttribute("default")) + .arg(formatAttribute("fixed"))); + return attribute; + } + + // parse attributes + if (hasAttribute(QString::fromLatin1("default"))) { + const QString value = readAttribute(QString::fromLatin1("default")); + attribute->setValueConstraint(XsdAttribute::ValueConstraint::Ptr(new XsdAttribute::ValueConstraint())); + attribute->valueConstraint()->setVariety(XsdAttribute::ValueConstraint::Default); + attribute->valueConstraint()->setValue(value); + } else if (hasAttribute(QString::fromLatin1("fixed"))) { + const QString value = readAttribute(QString::fromLatin1("fixed")); + attribute->setValueConstraint(XsdAttribute::ValueConstraint::Ptr(new XsdAttribute::ValueConstraint())); + attribute->valueConstraint()->setVariety(XsdAttribute::ValueConstraint::Fixed); + attribute->valueConstraint()->setValue(value); + } + + const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("attribute")); + if ((objectName.namespaceURI() == StandardNamespaces::xsi) && + (m_namePool->stringForLocalName(objectName.localName()) != QString::fromLatin1("type")) && + (m_namePool->stringForLocalName(objectName.localName()) != QString::fromLatin1("nil")) && + (m_namePool->stringForLocalName(objectName.localName()) != QString::fromLatin1("schemaLocation")) && + (m_namePool->stringForLocalName(objectName.localName()) != QString::fromLatin1("noNamespaceSchemaLocation"))) { + + error(QtXmlPatterns::tr("content of %1 attribute of %2 element must not be from namespace %3") + .arg(formatAttribute("name")) + .arg(formatElement("attribute")) + .arg(formatURI(QLatin1String("http://www.w3.org/2001/XMLSchema-instance")))); + return attribute; + } + if (m_namePool->stringForLocalName(objectName.localName()) == QString::fromLatin1("xmlns")) { + error(QtXmlPatterns::tr("%1 attribute of %2 element must not be %3") + .arg(formatAttribute("name")) + .arg(formatElement("attribute")) + .arg(formatData("xmlns"))); + return attribute; + } + attribute->setName(objectName); + + bool hasTypeAttribute = false; + bool hasTypeSpecified = false; + + if (hasAttribute(QString::fromLatin1("type"))) { + hasTypeAttribute = true; + + const QString type = readQNameAttribute(QString::fromLatin1("type"), "attribute"); + QXmlName typeName; + convertName(type, NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName + m_schemaResolver->addAttributeType(attribute, typeName, currentSourceLocation()); // add to resolver + hasTypeSpecified = true; + } + + validateIdAttribute("attribute"); + + TagValidationHandler tagValidator(XsdTagScope::GlobalAttribute, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + attribute->addAnnotation(annotation); + } else if (isSchemaTag(XsdSchemaToken::SimpleType, token, namespaceToken)) { + if (hasTypeAttribute) { + error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute") + .arg(formatElement("attribute")) + .arg(formatElement("simpleType")) + .arg(formatAttribute("type"))); + break; + } + + const XsdSimpleType::Ptr type = parseLocalSimpleType(); + type->setContext(attribute); + attribute->setType(type); + hasTypeSpecified = true; + + // add it to list of anonymous types as well + addAnonymousType(type); + } else { + parseUnknown(); + } + } + } + + if (!hasTypeSpecified) { + attribute->setType(BuiltinTypes::xsAnySimpleType); // default value + return attribute; + } + + tagValidator.finalize(); + + return attribute; +} + +XsdAttributeUse::Ptr XsdSchemaParser::parseLocalAttribute(const NamedSchemaComponent::Ptr &parent) +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Attribute, this); + + validateElement(XsdTagScope::LocalAttribute); + + bool hasRefAttribute = false; + bool hasTypeAttribute = false; + bool hasTypeSpecified = false; + + XsdAttributeUse::Ptr attributeUse; + if (hasAttribute(QString::fromLatin1("ref"))) { + const XsdAttributeReference::Ptr reference = XsdAttributeReference::Ptr(new XsdAttributeReference()); + reference->setType(XsdAttributeReference::AttributeUse); + reference->setSourceLocation(currentSourceLocation()); + + attributeUse = reference; + hasRefAttribute = true; + } else { + attributeUse = XsdAttributeUse::Ptr(new XsdAttributeUse()); + } + + if (hasAttribute(QString::fromLatin1("default")) && hasAttribute(QString::fromLatin1("fixed"))) { + error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together") + .arg(formatElement("attribute")) + .arg(formatAttribute("default")) + .arg(formatAttribute("fixed"))); + return attributeUse; + } + + if (hasRefAttribute) { + if (hasAttribute(QString::fromLatin1("form"))) { + error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together") + .arg(formatElement("attribute")) + .arg(formatAttribute("ref")) + .arg(formatAttribute("form"))); + return attributeUse; + } + if (hasAttribute(QString::fromLatin1("name"))) { + error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together") + .arg(formatElement("attribute")) + .arg(formatAttribute("ref")) + .arg(formatAttribute("name"))); + return attributeUse; + } + if (hasAttribute(QString::fromLatin1("type"))) { + error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together") + .arg(formatElement("attribute")) + .arg(formatAttribute("ref")) + .arg(formatAttribute("type"))); + return attributeUse; + } + } + + // parse attributes + + // default, fixed and use are handled by both, attribute use and attribute reference + if (hasAttribute(QString::fromLatin1("default"))) { + const QString value = readAttribute(QString::fromLatin1("default")); + attributeUse->setValueConstraint(XsdAttributeUse::ValueConstraint::Ptr(new XsdAttributeUse::ValueConstraint())); + attributeUse->valueConstraint()->setVariety(XsdAttributeUse::ValueConstraint::Default); + attributeUse->valueConstraint()->setValue(value); + } else if (hasAttribute(QString::fromLatin1("fixed"))) { + const QString value = readAttribute(QString::fromLatin1("fixed")); + attributeUse->setValueConstraint(XsdAttributeUse::ValueConstraint::Ptr(new XsdAttributeUse::ValueConstraint())); + attributeUse->valueConstraint()->setVariety(XsdAttributeUse::ValueConstraint::Fixed); + attributeUse->valueConstraint()->setValue(value); + } + + if (hasAttribute(QString::fromLatin1("use"))) { + const QString value = readAttribute(QString::fromLatin1("use")); + if (value != QString::fromLatin1("optional") && + value != QString::fromLatin1("prohibited") && + value != QString::fromLatin1("required")) { + attributeContentError("use", "attribute", value); + return attributeUse; + } + + if (value == QString::fromLatin1("optional")) + attributeUse->setUseType(XsdAttributeUse::OptionalUse); + else if (value == QString::fromLatin1("prohibited")) + attributeUse->setUseType(XsdAttributeUse::ProhibitedUse); + else if (value == QString::fromLatin1("required")) + attributeUse->setUseType(XsdAttributeUse::RequiredUse); + + if (attributeUse->valueConstraint() && attributeUse->valueConstraint()->variety() == XsdAttributeUse::ValueConstraint::Default && value != QString::fromLatin1("optional")) { + error(QtXmlPatterns::tr("%1 attribute of %2 element must have the value %3 because the %4 attribute is set") + .arg(formatAttribute("use")) + .arg(formatElement("attribute")) + .arg(formatData("optional")) + .arg(formatElement("default"))); + return attributeUse; + } + } + + const XsdAttribute::Ptr attribute(new XsdAttribute()); + + attributeUse->setAttribute(attribute); + m_componentLocationHash.insert(attribute, currentSourceLocation()); + + attribute->setScope(XsdAttribute::Scope::Ptr(new XsdAttribute::Scope())); + attribute->scope()->setVariety(XsdAttribute::Scope::Local); + attribute->scope()->setParent(parent); + + // now make a difference between attribute reference and attribute use + if (hasRefAttribute) { + const QString reference = readQNameAttribute(QString::fromLatin1("ref"), "attribute"); + QXmlName referenceName; + convertName(reference, NamespaceSupport::ElementName, referenceName); // translate qualified name into QXmlName + + const XsdAttributeReference::Ptr attributeReference = attributeUse; + attributeReference->setReferenceName(referenceName); + } else { + if (hasAttribute(QString::fromLatin1("name"))) { + const QString attributeName = readNameAttribute("attribute"); + + QXmlName objectName; + if (hasAttribute(QString::fromLatin1("form"))) { + const QString value = readAttribute(QString::fromLatin1("form")); + if (value != QString::fromLatin1("qualified") && value != QString::fromLatin1("unqualified")) { + attributeContentError("form", "attribute", value); + return attributeUse; + } + + if (value == QString::fromLatin1("qualified")) { + objectName = m_namePool->allocateQName(m_targetNamespace, attributeName); + } else { + objectName = m_namePool->allocateQName(QString(), attributeName); + } + } else { + if (m_attributeFormDefault == QString::fromLatin1("qualified")) { + objectName = m_namePool->allocateQName(m_targetNamespace, attributeName); + } else { + objectName = m_namePool->allocateQName(QString(), attributeName); + } + } + + if ((objectName.namespaceURI() == StandardNamespaces::xsi) && + (m_namePool->stringForLocalName(objectName.localName()) != QString::fromLatin1("type")) && + (m_namePool->stringForLocalName(objectName.localName()) != QString::fromLatin1("nil")) && + (m_namePool->stringForLocalName(objectName.localName()) != QString::fromLatin1("schemaLocation")) && + (m_namePool->stringForLocalName(objectName.localName()) != QString::fromLatin1("noNamespaceSchemaLocation"))) { + + error(QtXmlPatterns::tr("content of %1 attribute of %2 element must not be from namespace %3") + .arg(formatAttribute("name")) + .arg(formatElement("attribute")) + .arg(formatURI(QLatin1String("http://www.w3.org/2001/XMLSchema-instance")))); + return attributeUse; + } + if (m_namePool->stringForLocalName(objectName.localName()) == QString::fromLatin1("xmlns")) { + error(QtXmlPatterns::tr("%1 attribute of %2 element must not be %3") + .arg(formatAttribute("name")) + .arg(formatElement("attribute")) + .arg(formatData("xmlns"))); + return attributeUse; + } + + attribute->setName(objectName); + } + + if (hasAttribute(QString::fromLatin1("type"))) { + hasTypeAttribute = true; + + const QString type = readQNameAttribute(QString::fromLatin1("type"), "attribute"); + QXmlName typeName; + convertName(type, NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName + m_schemaResolver->addAttributeType(attribute, typeName, currentSourceLocation()); // add to resolver + hasTypeSpecified = true; + } + + if (attributeUse->valueConstraint()) { + //TODO: check whether assigning the value constraint of the attribute use to the attribute is correct + if (!attribute->valueConstraint()) + attribute->setValueConstraint(XsdAttribute::ValueConstraint::Ptr(new XsdAttribute::ValueConstraint())); + + attribute->valueConstraint()->setVariety((XsdAttribute::ValueConstraint::Variety)attributeUse->valueConstraint()->variety()); + attribute->valueConstraint()->setValue(attributeUse->valueConstraint()->value()); + attribute->valueConstraint()->setLexicalForm(attributeUse->valueConstraint()->lexicalForm()); + } + } + + validateIdAttribute("attribute"); + + TagValidationHandler tagValidator(XsdTagScope::LocalAttribute, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + attribute->addAnnotation(annotation); + } else if (isSchemaTag(XsdSchemaToken::SimpleType, token, namespaceToken)) { + if (hasTypeAttribute) { + error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute") + .arg(formatElement("attribute")) + .arg(formatElement("simpleType")) + .arg(formatAttribute("type"))); + break; + } + if (hasRefAttribute) { + error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute") + .arg(formatElement("attribute")) + .arg(formatElement("simpleType")) + .arg(formatAttribute("ref"))); + break; + } + + const XsdSimpleType::Ptr type = parseLocalSimpleType(); + type->setContext(attribute); + attribute->setType(type); + hasTypeSpecified = true; + + // add it to list of anonymous types as well + addAnonymousType(type); + } else { + parseUnknown(); + } + } + } + + if (!hasTypeSpecified) { + attribute->setType(BuiltinTypes::xsAnySimpleType); // default value + } + + tagValidator.finalize(); + + return attributeUse; +} + +XsdAttributeGroup::Ptr XsdSchemaParser::parseNamedAttributeGroup() +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::AttributeGroup, this); + + validateElement(XsdTagScope::NamedAttributeGroup); + + const XsdAttributeGroup::Ptr attributeGroup(new XsdAttributeGroup()); + + // parse attributes + const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("attributeGroup")); + attributeGroup->setName(objectName); + + validateIdAttribute("attributeGroup"); + + TagValidationHandler tagValidator(XsdTagScope::NamedAttributeGroup, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + attributeGroup->addAnnotation(annotation); + } else if (isSchemaTag(XsdSchemaToken::Attribute, token, namespaceToken)) { + const XsdAttributeUse::Ptr attributeUse = parseLocalAttribute(attributeGroup); + + if (attributeUse->useType() == XsdAttributeUse::ProhibitedUse) { + warning(QtXmlPatterns::tr("specifying use='prohibited' inside an attribute group has no effect")); + } else { + attributeGroup->addAttributeUse(attributeUse); + } + } else if (isSchemaTag(XsdSchemaToken::AttributeGroup, token, namespaceToken)) { + const XsdAttributeUse::Ptr attributeUse = parseReferredAttributeGroup(); + attributeGroup->addAttributeUse(attributeUse); + } else if (isSchemaTag(XsdSchemaToken::AnyAttribute, token, namespaceToken)) { + const XsdWildcard::Ptr wildcard = parseAnyAttribute(); + attributeGroup->setWildcard(wildcard); + } else { + parseUnknown(); + } + } + } + + tagValidator.finalize(); + + return attributeGroup; +} + +XsdAttributeUse::Ptr XsdSchemaParser::parseReferredAttributeGroup() +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::AttributeGroup, this); + + validateElement(XsdTagScope::ReferredAttributeGroup); + + const XsdAttributeReference::Ptr attributeReference(new XsdAttributeReference()); + attributeReference->setType(XsdAttributeReference::AttributeGroup); + attributeReference->setSourceLocation(currentSourceLocation()); + + // parse attributes + const QString reference = readQNameAttribute(QString::fromLatin1("ref"), "attributeGroup"); + QXmlName referenceName; + convertName(reference, NamespaceSupport::ElementName, referenceName); // translate qualified name into QXmlName + attributeReference->setReferenceName(referenceName); + + validateIdAttribute("attributeGroup"); + + TagValidationHandler tagValidator(XsdTagScope::ReferredAttributeGroup, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + attributeReference->addAnnotation(annotation); + } else { + parseUnknown(); + } + } + } + + tagValidator.finalize(); + + return attributeReference; +} + +XsdElement::Ptr XsdSchemaParser::parseGlobalElement() +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Element, this); + + validateElement(XsdTagScope::GlobalElement); + + const XsdElement::Ptr element(new XsdElement()); + element->setScope(XsdElement::Scope::Ptr(new XsdElement::Scope())); + element->scope()->setVariety(XsdElement::Scope::Global); + + bool hasTypeAttribute = false; + bool hasTypeSpecified = false; + bool hasSubstitutionGroup = false; + + // parse attributes + const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("element")); + element->setName(objectName); + + if (hasAttribute(QString::fromLatin1("abstract"))) { + const QString abstract = readAttribute(QString::fromLatin1("abstract")); + + const Boolean::Ptr value = Boolean::fromLexical(abstract); + if (value->hasError()) { + attributeContentError("abstract", "element", abstract, BuiltinTypes::xsBoolean); + return element; + } + + element->setIsAbstract(value->as()->value()); + } else { + element->setIsAbstract(false); // the default value + } + + if (hasAttribute(QString::fromLatin1("default")) && hasAttribute(QString::fromLatin1("fixed"))) { + error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together") + .arg(formatElement("element")) + .arg(formatAttribute("default")) + .arg(formatAttribute("fixed"))); + return element; + } + + if (hasAttribute(QString::fromLatin1("default"))) { + const QString value = readAttribute(QString::fromLatin1("default")); + element->setValueConstraint(XsdElement::ValueConstraint::Ptr(new XsdElement::ValueConstraint())); + element->valueConstraint()->setVariety(XsdElement::ValueConstraint::Default); + element->valueConstraint()->setValue(value); + } else if (hasAttribute(QString::fromLatin1("fixed"))) { + const QString value = readAttribute(QString::fromLatin1("fixed")); + element->setValueConstraint(XsdElement::ValueConstraint::Ptr(new XsdElement::ValueConstraint())); + element->valueConstraint()->setVariety(XsdElement::ValueConstraint::Fixed); + element->valueConstraint()->setValue(value); + } + + element->setDisallowedSubstitutions(readBlockingConstraintAttribute(NamedSchemaComponent::ExtensionConstraint | NamedSchemaComponent::RestrictionConstraint | NamedSchemaComponent::SubstitutionConstraint, "element")); + element->setSubstitutionGroupExclusions(readDerivationConstraintAttribute(SchemaType::ExtensionConstraint | SchemaType::RestrictionConstraint, "element")); + + if (hasAttribute(QString::fromLatin1("nillable"))) { + const QString nillable = readAttribute(QString::fromLatin1("nillable")); + + const Boolean::Ptr value = Boolean::fromLexical(nillable); + if (value->hasError()) { + attributeContentError("nillable", "element", nillable, BuiltinTypes::xsBoolean); + return element; + } + + element->setIsNillable(value->as()->value()); + } else { + element->setIsNillable(false); // the default value + } + + if (hasAttribute(QString::fromLatin1("type"))) { + const QString type = readQNameAttribute(QString::fromLatin1("type"), "element"); + QXmlName typeName; + convertName(type, NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName + m_schemaResolver->addElementType(element, typeName, currentSourceLocation()); // add to resolver + + hasTypeAttribute = true; + hasTypeSpecified = true; + } + + if (hasAttribute(QString::fromLatin1("substitutionGroup"))) { + QList elementNames; + + const QString value = readAttribute(QString::fromLatin1("substitutionGroup")); + const QStringList substitutionGroups = value.split(QLatin1Char(' '), QString::SkipEmptyParts); + if (substitutionGroups.isEmpty()) { + attributeContentError("substitutionGroup", "element", value, BuiltinTypes::xsQName); + return element; + } + + for (int i = 0; i < substitutionGroups.count(); ++i) { + const QString value = substitutionGroups.at(i).simplified(); + if (!XPathHelper::isQName(value)) { + attributeContentError("substitutionGroup", "element", value, BuiltinTypes::xsQName); + return element; + } + + QXmlName elementName; + convertName(value, NamespaceSupport::ElementName, elementName); // translate qualified name into QXmlName + elementNames.append(elementName); + } + + m_schemaResolver->addSubstitutionGroupAffiliation(element, elementNames, currentSourceLocation()); // add to resolver + + hasSubstitutionGroup = true; + } + + validateIdAttribute("element"); + + XsdAlternative::List alternatives; + + TagValidationHandler tagValidator(XsdTagScope::GlobalElement, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + element->addAnnotation(annotation); + } else if (isSchemaTag(XsdSchemaToken::SimpleType, token, namespaceToken)) { + if (hasTypeAttribute) { + error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute") + .arg(formatElement("element")) + .arg(formatElement("simpleType")) + .arg(formatAttribute("type"))); + return element; + } + + const XsdSimpleType::Ptr type = parseLocalSimpleType(); + type->setContext(element); + element->setType(type); + + // add it to list of anonymous types as well + addAnonymousType(type); + + hasTypeSpecified = true; + } else if (isSchemaTag(XsdSchemaToken::ComplexType, token, namespaceToken)) { + if (hasTypeAttribute) { + error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute") + .arg(formatElement("element")) + .arg(formatElement("complexType")) + .arg(formatAttribute("type"))); + return element; + } + + const XsdComplexType::Ptr type = parseLocalComplexType(); + type->setContext(element); + element->setType(type); + + // add it to list of anonymous types as well + addAnonymousType(type); + + hasTypeSpecified = true; + } else if (isSchemaTag(XsdSchemaToken::Alternative, token, namespaceToken)) { + const XsdAlternative::Ptr alternative = parseAlternative(); + alternatives.append(alternative); + } else if (isSchemaTag(XsdSchemaToken::Unique, token, namespaceToken)) { + const XsdIdentityConstraint::Ptr constraint = parseUnique(); + element->addIdentityConstraint(constraint); + } else if (isSchemaTag(XsdSchemaToken::Key, token, namespaceToken)) { + const XsdIdentityConstraint::Ptr constraint = parseKey(); + element->addIdentityConstraint(constraint); + } else if (isSchemaTag(XsdSchemaToken::Keyref, token, namespaceToken)) { + const XsdIdentityConstraint::Ptr constraint = parseKeyRef(element); + element->addIdentityConstraint(constraint); + } else { + parseUnknown(); + } + } + } + + tagValidator.finalize(); + + if (!hasTypeSpecified) { + if (hasSubstitutionGroup) + m_schemaResolver->addSubstitutionGroupType(element); + else + element->setType(BuiltinTypes::xsAnyType); + } + + if (!alternatives.isEmpty()) { + element->setTypeTable(XsdElement::TypeTable::Ptr(new XsdElement::TypeTable())); + + for (int i = 0; i < alternatives.count(); ++i) { + if (alternatives.at(i)->test()) + element->typeTable()->addAlternative(alternatives.at(i)); + + if (i == (alternatives.count() - 1)) { // the final one + if (!alternatives.at(i)->test()) { + element->typeTable()->setDefaultTypeDefinition(alternatives.at(i)); + } else { + const XsdAlternative::Ptr alternative(new XsdAlternative()); + if (element->type()) + alternative->setType(element->type()); + else + m_schemaResolver->addAlternativeType(alternative, element); // add to resolver + + element->typeTable()->setDefaultTypeDefinition(alternative); + } + } + } + } + + return element; +} + +XsdTerm::Ptr XsdSchemaParser::parseLocalElement(const XsdParticle::Ptr &particle, const NamedSchemaComponent::Ptr &parent) +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Element, this); + + validateElement(XsdTagScope::LocalElement); + + bool hasRefAttribute = false; + bool hasTypeAttribute = false; + bool hasTypeSpecified = false; + + XsdTerm::Ptr term; + XsdElement::Ptr element; + if (hasAttribute(QString::fromLatin1("ref"))) { + term = XsdReference::Ptr(new XsdReference()); + hasRefAttribute = true; + } else { + term = XsdElement::Ptr(new XsdElement()); + element = term; + } + + if (hasRefAttribute) { + if (hasAttribute(QString::fromLatin1("name"))) { + error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together") + .arg(formatElement("element")) + .arg(formatAttribute("ref")) + .arg(formatAttribute("name"))); + return term; + } else if (hasAttribute(QString::fromLatin1("block"))) { + error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together") + .arg(formatElement("element")) + .arg(formatAttribute("ref")) + .arg(formatAttribute("block"))); + return term; + } else if (hasAttribute(QString::fromLatin1("nillable"))) { + error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together") + .arg(formatElement("element")) + .arg(formatAttribute("ref")) + .arg(formatAttribute("nillable"))); + return term; + } else if (hasAttribute(QString::fromLatin1("default"))) { + error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together") + .arg(formatElement("element")) + .arg(formatAttribute("ref")) + .arg(formatAttribute("default"))); + return term; + } else if (hasAttribute(QString::fromLatin1("fixed"))) { + error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together") + .arg(formatElement("element")) + .arg(formatAttribute("ref")) + .arg(formatAttribute("fixed"))); + return term; + } else if (hasAttribute(QString::fromLatin1("form"))) { + error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together") + .arg(formatElement("element")) + .arg(formatAttribute("ref")) + .arg(formatAttribute("form"))); + return term; + } else if (hasAttribute(QString::fromLatin1("type"))) { + error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together") + .arg(formatElement("element")) + .arg(formatAttribute("ref")) + .arg(formatAttribute("type"))); + return term; + } + } + + // parse attributes + if (!parseMinMaxConstraint(particle, "element")) { + return element; + } + + if (!hasAttribute(QString::fromLatin1("name")) && !hasAttribute(QString::fromLatin1("ref"))) { + error(QtXmlPatterns::tr("%1 element must have either %2 or %3 attribute") + .arg(formatElement("element")) + .arg(formatAttribute("name")) + .arg(formatAttribute("ref"))); + return element; + } + + if (hasRefAttribute) { + const QString ref = readQNameAttribute(QString::fromLatin1("ref"), "element"); + QXmlName referenceName; + convertName(ref, NamespaceSupport::ElementName, referenceName); // translate qualified name into QXmlName + + const XsdReference::Ptr reference = term; + reference->setReferenceName(referenceName); + reference->setType(XsdReference::Element); + reference->setSourceLocation(currentSourceLocation()); + } else { + element->setScope(XsdElement::Scope::Ptr(new XsdElement::Scope())); + element->scope()->setVariety(XsdElement::Scope::Local); + element->scope()->setParent(parent); + + if (hasAttribute(QString::fromLatin1("name"))) { + const QString elementName = readNameAttribute("element"); + + QXmlName objectName; + if (hasAttribute(QString::fromLatin1("form"))) { + const QString value = readAttribute(QString::fromLatin1("form")); + if (value != QString::fromLatin1("qualified") && value != QString::fromLatin1("unqualified")) { + attributeContentError("form", "element", value); + return element; + } + + if (value == QString::fromLatin1("qualified")) { + objectName = m_namePool->allocateQName(m_targetNamespace, elementName); + } else { + objectName = m_namePool->allocateQName(QString(), elementName); + } + } else { + if (m_elementFormDefault == QString::fromLatin1("qualified")) { + objectName = m_namePool->allocateQName(m_targetNamespace, elementName); + } else { + objectName = m_namePool->allocateQName(QString(), elementName); + } + } + + element->setName(objectName); + } + + if (hasAttribute(QString::fromLatin1("nillable"))) { + const QString nillable = readAttribute(QString::fromLatin1("nillable")); + + const Boolean::Ptr value = Boolean::fromLexical(nillable); + if (value->hasError()) { + attributeContentError("nillable", "element", nillable, BuiltinTypes::xsBoolean); + return term; + } + + element->setIsNillable(value->as()->value()); + } else { + element->setIsNillable(false); // the default value + } + + if (hasAttribute(QString::fromLatin1("default")) && hasAttribute(QString::fromLatin1("fixed"))) { + error(QtXmlPatterns::tr("%1 element must not have %2 and %3 attribute together") + .arg(formatElement("element")) + .arg(formatAttribute("default")) + .arg(formatAttribute("fixed"))); + return element; + } + + if (hasAttribute(QString::fromLatin1("default"))) { + const QString value = readAttribute(QString::fromLatin1("default")); + element->setValueConstraint(XsdElement::ValueConstraint::Ptr(new XsdElement::ValueConstraint())); + element->valueConstraint()->setVariety(XsdElement::ValueConstraint::Default); + element->valueConstraint()->setValue(value); + } else if (hasAttribute(QString::fromLatin1("fixed"))) { + const QString value = readAttribute(QString::fromLatin1("fixed")); + element->setValueConstraint(XsdElement::ValueConstraint::Ptr(new XsdElement::ValueConstraint())); + element->valueConstraint()->setVariety(XsdElement::ValueConstraint::Fixed); + element->valueConstraint()->setValue(value); + } + + if (hasAttribute(QString::fromLatin1("type"))) { + const QString type = readQNameAttribute(QString::fromLatin1("type"), "element"); + QXmlName typeName; + convertName(type, NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName + m_schemaResolver->addElementType(element, typeName, currentSourceLocation()); // add to resolver + + hasTypeAttribute = true; + hasTypeSpecified = true; + } + + element->setDisallowedSubstitutions(readBlockingConstraintAttribute(NamedSchemaComponent::ExtensionConstraint | NamedSchemaComponent::RestrictionConstraint | NamedSchemaComponent::SubstitutionConstraint, "element")); + } + + validateIdAttribute("element"); + + XsdAlternative::List alternatives; + + TagValidationHandler tagValidator(XsdTagScope::LocalElement, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + element->addAnnotation(annotation); + } else if (isSchemaTag(XsdSchemaToken::SimpleType, token, namespaceToken)) { + if (hasRefAttribute) { + error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute") + .arg(formatElement("element")) + .arg(formatElement("simpleType")) + .arg(formatAttribute("ref"))); + return term; + } else if (hasTypeAttribute) { + error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute") + .arg(formatElement("element")) + .arg(formatElement("simpleType")) + .arg(formatAttribute("type"))); + return term; + } + + const XsdSimpleType::Ptr type = parseLocalSimpleType(); + type->setContext(element); + element->setType(type); + + // add it to list of anonymous types as well + addAnonymousType(type); + + hasTypeSpecified = true; + } else if (isSchemaTag(XsdSchemaToken::ComplexType, token, namespaceToken)) { + if (hasRefAttribute) { + error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute") + .arg(formatElement("element")) + .arg(formatElement("complexType")) + .arg(formatAttribute("ref"))); + return term; + } else if (hasTypeAttribute) { + error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute") + .arg(formatElement("element")) + .arg(formatElement("complexType")) + .arg(formatAttribute("type"))); + return term; + } + + const XsdComplexType::Ptr type = parseLocalComplexType(); + type->setContext(element); + element->setType(type); + + // add it to list of anonymous types as well + addAnonymousType(type); + + hasTypeSpecified = true; + } else if (isSchemaTag(XsdSchemaToken::Alternative, token, namespaceToken)) { + if (hasRefAttribute) { + error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute") + .arg(formatElement("element")) + .arg(formatElement("alternative")) + .arg(formatAttribute("ref"))); + return term; + } + + const XsdAlternative::Ptr alternative = parseAlternative(); + alternatives.append(alternative); + } else if (isSchemaTag(XsdSchemaToken::Unique, token, namespaceToken)) { + if (hasRefAttribute) { + error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute") + .arg(formatElement("element")) + .arg(formatElement("unique")) + .arg(formatAttribute("ref"))); + return term; + } + + const XsdIdentityConstraint::Ptr constraint = parseUnique(); + element->addIdentityConstraint(constraint); + } else if (isSchemaTag(XsdSchemaToken::Key, token, namespaceToken)) { + if (hasRefAttribute) { + error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute") + .arg(formatElement("element")) + .arg(formatElement("key")) + .arg(formatAttribute("ref"))); + return term; + } + + const XsdIdentityConstraint::Ptr constraint = parseKey(); + element->addIdentityConstraint(constraint); + } else if (isSchemaTag(XsdSchemaToken::Keyref, token, namespaceToken)) { + if (hasRefAttribute) { + error(QtXmlPatterns::tr("%1 element with %2 child element must not have a %3 attribute") + .arg(formatElement("element")) + .arg(formatElement("keyref")) + .arg(formatAttribute("ref"))); + return term; + } + + const XsdIdentityConstraint::Ptr constraint = parseKeyRef(element); + element->addIdentityConstraint(constraint); + } else { + parseUnknown(); + } + } + } + + tagValidator.finalize(); + + if (!hasTypeSpecified && !hasRefAttribute) + element->setType(BuiltinTypes::xsAnyType); + + if (!hasRefAttribute && !alternatives.isEmpty()) { + element->setTypeTable(XsdElement::TypeTable::Ptr(new XsdElement::TypeTable())); + + for (int i = 0; i < alternatives.count(); ++i) { + if (alternatives.at(i)->test()) + element->typeTable()->addAlternative(alternatives.at(i)); + + if (i == (alternatives.count() - 1)) { // the final one + if (!alternatives.at(i)->test()) { + element->typeTable()->setDefaultTypeDefinition(alternatives.at(i)); + } else { + const XsdAlternative::Ptr alternative(new XsdAlternative()); + if (element->type()) + alternative->setType(element->type()); + else + m_schemaResolver->addAlternativeType(alternative, element); // add to resolver + + element->typeTable()->setDefaultTypeDefinition(alternative); + } + } + } + } + + return term; +} + +XsdIdentityConstraint::Ptr XsdSchemaParser::parseUnique() +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Unique, this); + + validateElement(XsdTagScope::Unique); + + const XsdIdentityConstraint::Ptr constraint(new XsdIdentityConstraint()); + constraint->setCategory(XsdIdentityConstraint::Unique); + + // parse attributes + const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("unique")); + constraint->setName(objectName); + + validateIdAttribute("unique"); + + TagValidationHandler tagValidator(XsdTagScope::Unique, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + constraint->addAnnotation(annotation); + } else if (isSchemaTag(XsdSchemaToken::Selector, token, namespaceToken)) { + parseSelector(constraint); + } else if (isSchemaTag(XsdSchemaToken::Field, token, namespaceToken)) { + parseField(constraint); + } else { + parseUnknown(); + } + } + } + + // add constraint to schema for further checking + addIdentityConstraint(constraint); + + tagValidator.finalize(); + + return constraint; +} + +XsdIdentityConstraint::Ptr XsdSchemaParser::parseKey() +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Key, this); + + validateElement(XsdTagScope::Key); + + const XsdIdentityConstraint::Ptr constraint(new XsdIdentityConstraint()); + constraint->setCategory(XsdIdentityConstraint::Key); + + // parse attributes + const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("key")); + constraint->setName(objectName); + + validateIdAttribute("key"); + + TagValidationHandler tagValidator(XsdTagScope::Key, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + constraint->addAnnotation(annotation); + } else if (isSchemaTag(XsdSchemaToken::Selector, token, namespaceToken)) { + parseSelector(constraint); + } else if (isSchemaTag(XsdSchemaToken::Field, token, namespaceToken)) { + parseField(constraint); + } else { + parseUnknown(); + } + } + } + + // add constraint to schema for further checking + addIdentityConstraint(constraint); + + tagValidator.finalize(); + + return constraint; +} + +XsdIdentityConstraint::Ptr XsdSchemaParser::parseKeyRef(const XsdElement::Ptr &element) +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Keyref, this); + + validateElement(XsdTagScope::KeyRef); + + const XsdIdentityConstraint::Ptr constraint(new XsdIdentityConstraint()); + constraint->setCategory(XsdIdentityConstraint::KeyReference); + + // parse attributes + const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("keyref")); + constraint->setName(objectName); + + const QString refer = readQNameAttribute(QString::fromLatin1("refer"), "keyref"); + QXmlName referenceName; + convertName(refer, NamespaceSupport::ElementName, referenceName); // translate qualified name into QXmlName + m_schemaResolver->addKeyReference(element, constraint, referenceName, currentSourceLocation()); // add to resolver + + validateIdAttribute("keyref"); + + TagValidationHandler tagValidator(XsdTagScope::KeyRef, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + constraint->addAnnotation(annotation); + } else if (isSchemaTag(XsdSchemaToken::Selector, token, namespaceToken)) { + parseSelector(constraint); + } else if (isSchemaTag(XsdSchemaToken::Field, token, namespaceToken)) { + parseField(constraint); + } else { + parseUnknown(); + } + } + } + + // add constraint to schema for further checking + addIdentityConstraint(constraint); + + tagValidator.finalize(); + + return constraint; +} + +void XsdSchemaParser::parseSelector(const XsdIdentityConstraint::Ptr &ptr) +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Selector, this); + + validateElement(XsdTagScope::Selector); + + // parse attributes + const XsdXPathExpression::Ptr expression = readXPathExpression("selector"); + + const QString xpath = readXPathAttribute(QString::fromLatin1("xpath"), XPathSelector, "selector"); + expression->setExpression(xpath); + + ptr->setSelector(expression); + + validateIdAttribute("selector"); + + TagValidationHandler tagValidator(XsdTagScope::Selector, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + expression->addAnnotation(annotation); + } else { + parseUnknown(); + } + } + } + + tagValidator.finalize(); +} + +void XsdSchemaParser::parseField(const XsdIdentityConstraint::Ptr &ptr) +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Field, this); + + validateElement(XsdTagScope::Field); + + // parse attributes + const XsdXPathExpression::Ptr expression = readXPathExpression("field"); + + const QString xpath = readXPathAttribute(QString::fromLatin1("xpath"), XPathField, "field"); + expression->setExpression(xpath); + + ptr->addField(expression); + + validateIdAttribute("field"); + + TagValidationHandler tagValidator(XsdTagScope::Field, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + expression->addAnnotation(annotation); + } else { + parseUnknown(); + } + } + } + + tagValidator.finalize(); +} + +XsdAlternative::Ptr XsdSchemaParser::parseAlternative() +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Alternative, this); + + validateElement(XsdTagScope::Alternative); + + const XsdAlternative::Ptr alternative(new XsdAlternative()); + + bool hasTypeSpecified = false; + + if (hasAttribute(QString::fromLatin1("test"))) { + const XsdXPathExpression::Ptr expression = readXPathExpression("alternative"); + + const QString test = readXPathAttribute(QString::fromLatin1("test"), XPath20, "alternative"); + expression->setExpression(test); + + alternative->setTest(expression); + } + + if (hasAttribute(QString::fromLatin1("type"))) { + const QString type = readQNameAttribute(QString::fromLatin1("type"), "alternative"); + QXmlName typeName; + convertName(type, NamespaceSupport::ElementName, typeName); // translate qualified name into QXmlName + m_schemaResolver->addAlternativeType(alternative, typeName, currentSourceLocation()); // add to resolver + + hasTypeSpecified = true; + } + + validateIdAttribute("alternative"); + + TagValidationHandler tagValidator(XsdTagScope::Alternative, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + alternative->addAnnotation(annotation); + } else if (isSchemaTag(XsdSchemaToken::SimpleType, token, namespaceToken)) { + const XsdSimpleType::Ptr type = parseLocalSimpleType(); + alternative->setType(type); + + // add it to list of anonymous types as well + addAnonymousType(type); + + hasTypeSpecified = true; + } else if (isSchemaTag(XsdSchemaToken::ComplexType, token, namespaceToken)) { + const XsdComplexType::Ptr type = parseLocalComplexType(); + alternative->setType(type); + + // add it to list of anonymous types as well + addAnonymousType(type); + + hasTypeSpecified = true; + } else { + parseUnknown(); + } + } + } + + tagValidator.finalize(); + + if (!hasTypeSpecified) { + error(QtXmlPatterns::tr("%1 element must have either %2 attribute or %3 or %4 as child element") + .arg(formatElement("alternative")) + .arg(formatAttribute("type")) + .arg(formatElement("simpleType")) + .arg(formatElement("complexType"))); + return alternative; + } + + return alternative; +} + +XsdNotation::Ptr XsdSchemaParser::parseNotation() +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Notation, this); + + validateElement(XsdTagScope::Notation); + + const XsdNotation::Ptr notation(new XsdNotation()); + + // parse attributes + const QXmlName objectName = m_namePool->allocateQName(m_targetNamespace, readNameAttribute("notation")); + notation->setName(objectName); + + bool hasOptionalAttribute = false; + + if (hasAttribute(QString::fromLatin1("public"))) { + const QString value = readAttribute(QString::fromLatin1("public")); + if (!value.isEmpty()) { + const DerivedString::Ptr publicId = DerivedString::fromLexical(m_namePool, value); + if (publicId->hasError()) { + attributeContentError("public", "notation", value, BuiltinTypes::xsToken); + return notation; + } + notation->setPublicId(publicId); + } + + hasOptionalAttribute = true; + } + + if (hasAttribute(QString::fromLatin1("system"))) { + const QString value = readAttribute(QString::fromLatin1("system")); + if (!isValidUri(value)) { + attributeContentError("system", "notation", value, BuiltinTypes::xsAnyURI); + return notation; + } + + if (!value.isEmpty()) { + const AnyURI::Ptr systemId = AnyURI::fromLexical(value); + notation->setSystemId(systemId); + } + + hasOptionalAttribute = true; + } + + if (!hasOptionalAttribute) { + error(QtXmlPatterns::tr("%1 element requires either %2 or %3 attribute") + .arg(formatElement("notation")) + .arg(formatAttribute("public")) + .arg(formatAttribute("system"))); + return notation; + } + + validateIdAttribute("notation"); + + TagValidationHandler tagValidator(XsdTagScope::Notation, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isCharacters() || isEntityReference()) { + if (!text().toString().trimmed().isEmpty()) { + error(QtXmlPatterns::tr("text or entity references not allowed inside %1 element").arg(formatElement("notation"))); + return notation; + } + } + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + notation->addAnnotation(annotation); + } else { + parseUnknown(); + } + } + } + + tagValidator.finalize(); + + return notation; +} + +XsdWildcard::Ptr XsdSchemaParser::parseAny(const XsdParticle::Ptr &particle) +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::Any, this); + + validateElement(XsdTagScope::Any); + + const XsdWildcard::Ptr wildcard(new XsdWildcard()); + + // parse attributes + if (!parseMinMaxConstraint(particle, "any")) { + return wildcard; + } + + if (hasAttribute(QString::fromLatin1("namespace"))) { + const QSet values = readAttribute(QString::fromLatin1("namespace")).split(QLatin1Char(' '), QString::SkipEmptyParts).toSet(); + if ((values.contains(QString::fromLatin1("##any")) || values.contains(QString::fromLatin1("##other"))) && values.count() != 1) { + error(QtXmlPatterns::tr("%1 attribute of %2 element must contain %3, %4 or a list of URIs") + .arg(formatAttribute("namespace")) + .arg(formatElement("any")) + .arg(formatData("##any")) + .arg(formatData("##other"))); + return wildcard; + } + + if (values.contains(QString::fromLatin1("##any"))) { + wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Any); + } else if (values.contains(QString::fromLatin1("##other"))) { + wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Not); + if (!m_targetNamespace.isEmpty()) + wildcard->namespaceConstraint()->setNamespaces(QSet() << m_targetNamespace); + else + wildcard->namespaceConstraint()->setNamespaces(QSet() << XsdWildcard::absentNamespace()); + } else { + wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Enumeration); + QStringList newValues = values.toList(); + + // replace the ##targetNamespace entry + for (int i = 0; i < newValues.count(); ++i) { + if (newValues.at(i) == QString::fromLatin1("##targetNamespace")) { + if (!m_targetNamespace.isEmpty()) + newValues[i] = m_targetNamespace; + else + newValues[i] = XsdWildcard::absentNamespace(); + } else if (newValues.at(i) == QString::fromLatin1("##local")) { + newValues[i] = XsdWildcard::absentNamespace(); + } + } + + // check for invalid URIs + for (int i = 0; i < newValues.count(); ++i) { + const QString stringValue = newValues.at(i); + if (stringValue == XsdWildcard::absentNamespace()) + continue; + + if (!isValidUri(stringValue)) { + attributeContentError("namespace", "any", stringValue, BuiltinTypes::xsAnyURI); + return wildcard; + } + } + + wildcard->namespaceConstraint()->setNamespaces(newValues.toSet()); + } + } else { + wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Any); + } + + if (hasAttribute(QString::fromLatin1("processContents"))) { + const QString value = readAttribute(QString::fromLatin1("processContents")); + if (value != QString::fromLatin1("lax") && + value != QString::fromLatin1("skip") && + value != QString::fromLatin1("strict")) { + attributeContentError("processContents", "any", value); + return wildcard; + } + + if (value == QString::fromLatin1("lax")) { + wildcard->setProcessContents(XsdWildcard::Lax); + } else if (value == QString::fromLatin1("skip")) { + wildcard->setProcessContents(XsdWildcard::Skip); + } else if (value == QString::fromLatin1("strict")) { + wildcard->setProcessContents(XsdWildcard::Strict); + } + } else { + wildcard->setProcessContents(XsdWildcard::Strict); + } + + validateIdAttribute("any"); + + TagValidationHandler tagValidator(XsdTagScope::Any, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + wildcard->addAnnotation(annotation); + } else { + parseUnknown(); + } + } + } + + tagValidator.finalize(); + + return wildcard; +} + +XsdWildcard::Ptr XsdSchemaParser::parseAnyAttribute() +{ + const ElementNamespaceHandler namespaceHandler(XsdSchemaToken::AnyAttribute, this); + + validateElement(XsdTagScope::AnyAttribute); + + const XsdWildcard::Ptr wildcard(new XsdWildcard()); + + // parse attributes + if (hasAttribute(QString::fromLatin1("namespace"))) { + const QSet values = readAttribute(QString::fromLatin1("namespace")).split(QLatin1Char(' '), QString::SkipEmptyParts).toSet(); + if ((values.contains(QString::fromLatin1("##any")) || values.contains(QString::fromLatin1("##other"))) && values.count() != 1) { + error(QtXmlPatterns::tr("%1 attribute of %2 element must contain %3, %4 or a list of URIs") + .arg(formatAttribute("namespace")) + .arg(formatElement("anyAttribute")) + .arg(formatData("##any")) + .arg(formatData("##other"))); + return wildcard; + } + + if (values.contains(QString::fromLatin1("##any"))) { + wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Any); + } else if (values.contains(QString::fromLatin1("##other"))) { + wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Not); + if (!m_targetNamespace.isEmpty()) + wildcard->namespaceConstraint()->setNamespaces(QSet() << m_targetNamespace); + else + wildcard->namespaceConstraint()->setNamespaces(QSet() << XsdWildcard::absentNamespace()); + } else { + wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Enumeration); + QStringList newValues = values.toList(); + + // replace the ##targetNamespace entry + for (int i = 0; i < newValues.count(); ++i) { + if (newValues.at(i) == QString::fromLatin1("##targetNamespace")) { + if (!m_targetNamespace.isEmpty()) + newValues[i] = m_targetNamespace; + else + newValues[i] = XsdWildcard::absentNamespace(); + } else if (newValues.at(i) == QString::fromLatin1("##local")) { + newValues[i] = XsdWildcard::absentNamespace(); + } + } + + // check for invalid URIs + for (int i = 0; i < newValues.count(); ++i) { + const QString stringValue = newValues.at(i); + if (stringValue == XsdWildcard::absentNamespace()) + continue; + + if (!isValidUri(stringValue)) { + attributeContentError("namespace", "anyAttribute", stringValue, BuiltinTypes::xsAnyURI); + return wildcard; + } + } + + wildcard->namespaceConstraint()->setNamespaces(newValues.toSet()); + } + } else { + wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Any); + } + + if (hasAttribute(QString::fromLatin1("processContents"))) { + const QString value = readAttribute(QString::fromLatin1("processContents")); + if (value != QString::fromLatin1("lax") && + value != QString::fromLatin1("skip") && + value != QString::fromLatin1("strict")) { + attributeContentError("processContents", "anyAttribute", value); + return wildcard; + } + + if (value == QString::fromLatin1("lax")) { + wildcard->setProcessContents(XsdWildcard::Lax); + } else if (value == QString::fromLatin1("skip")) { + wildcard->setProcessContents(XsdWildcard::Skip); + } else if (value == QString::fromLatin1("strict")) { + wildcard->setProcessContents(XsdWildcard::Strict); + } + } else { + wildcard->setProcessContents(XsdWildcard::Strict); + } + + validateIdAttribute("anyAttribute"); + + TagValidationHandler tagValidator(XsdTagScope::AnyAttribute, this, m_namePool); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) { + const XsdSchemaToken::NodeName token = XsdSchemaToken::toToken(name()); + const XsdSchemaToken::NodeName namespaceToken = XsdSchemaToken::toToken(namespaceUri()); + + tagValidator.validate(token); + + if (isSchemaTag(XsdSchemaToken::Annotation, token, namespaceToken)) { + const XsdAnnotation::Ptr annotation = parseAnnotation(); + wildcard->addAnnotation(annotation); + } else { + parseUnknown(); + } + } + } + + tagValidator.finalize(); + + return wildcard; +} + + +void XsdSchemaParser::parseUnknownDocumentation() +{ + Q_ASSERT(isStartElement()); + m_namespaceSupport.pushContext(); + m_namespaceSupport.setPrefixes(namespaceDeclarations()); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) + parseUnknownDocumentation(); + } + + m_namespaceSupport.popContext(); +} + +void XsdSchemaParser::parseUnknown() +{ + Q_ASSERT(isStartElement()); + m_namespaceSupport.pushContext(); + m_namespaceSupport.setPrefixes(namespaceDeclarations()); + + error(QtXmlPatterns::tr("%1 element is not allowed in this context").arg(formatElement(name().toString()))); + + while (!atEnd()) { + readNext(); + + if (isEndElement()) + break; + + if (isStartElement()) + parseUnknown(); + } + + m_namespaceSupport.popContext(); +} + +bool XsdSchemaParser::parseMinMaxConstraint(const XsdParticle::Ptr &particle, const char *elementName) +{ + if (hasAttribute(QString::fromLatin1("minOccurs"))) { + const QString value = readAttribute(QString::fromLatin1("minOccurs")); + + DerivedInteger::Ptr integer = DerivedInteger::fromLexical(m_namePool, value); + if (integer->hasError()) { + attributeContentError("minOccurs", elementName, value, BuiltinTypes::xsNonNegativeInteger); + return false; + } else { + particle->setMinimumOccurs(integer->as< DerivedInteger >()->storedValue()); + } + } else { + particle->setMinimumOccurs(1); + } + + if (hasAttribute(QString::fromLatin1("maxOccurs"))) { + const QString value = readAttribute(QString::fromLatin1("maxOccurs")); + + if (value == QString::fromLatin1("unbounded")) { + particle->setMaximumOccursUnbounded(true); + } else { + particle->setMaximumOccursUnbounded(false); + DerivedInteger::Ptr integer = DerivedInteger::fromLexical(m_namePool, value); + if (integer->hasError()) { + attributeContentError("maxOccurs", elementName, value, BuiltinTypes::xsNonNegativeInteger); + return false; + } else { + particle->setMaximumOccurs(integer->as< DerivedInteger >()->storedValue()); + } + } + } else { + particle->setMaximumOccursUnbounded(false); + particle->setMaximumOccurs(1); + } + + if (!particle->maximumOccursUnbounded()) { + if (particle->maximumOccurs() < particle->minimumOccurs()) { + error(QtXmlPatterns::tr("%1 attribute of %2 element has larger value than %3 attribute") + .arg(formatAttribute("minOccurs")) + .arg(formatElement(elementName)) + .arg(formatAttribute("maxOccurs"))); + return false; + } + } + + return true; +} + +QSourceLocation XsdSchemaParser::currentSourceLocation() const +{ + QSourceLocation location; + location.setLine(lineNumber()); + location.setColumn(columnNumber()); + location.setUri(m_documentURI); + + return location; +} + +void XsdSchemaParser::convertName(const QString &qualifiedName, NamespaceSupport::NameType type, QXmlName &name) +{ + bool result = m_namespaceSupport.processName(qualifiedName, type, name); + if (!result) { + error(QtXmlPatterns::tr("prefix of qualified name %1 is not defined").arg(formatKeyword(qualifiedName))); + } +} + +QString XsdSchemaParser::readNameAttribute(const char *elementName) +{ + const QString value = readAttribute(QString::fromLatin1("name")).simplified(); + if (!QXmlUtils::isNCName(value)) { + attributeContentError("name", elementName, value, BuiltinTypes::xsNCName); + return QString(); + } else { + return value; + } +} + +QString XsdSchemaParser::readQNameAttribute(const QString &typeAttribute, const char *elementName) +{ + const QString value = readAttribute(typeAttribute).simplified(); + if (!XPathHelper::isQName(value)) { + attributeContentError(typeAttribute.toLatin1(), elementName, value, BuiltinTypes::xsQName); + return QString(); + } else { + return value; + } +} + +QString XsdSchemaParser::readNamespaceAttribute(const QString &attributeName, const char *elementName) +{ + const QString value = readAttribute(attributeName); + if (value.isEmpty()) { + attributeContentError(attributeName.toLatin1(), elementName, value, BuiltinTypes::xsAnyURI); + return QString(); + } + + return value; +} + +SchemaType::DerivationConstraints XsdSchemaParser::readDerivationConstraintAttribute(const SchemaType::DerivationConstraints &allowedConstraints, const char *elementName) +{ + // first convert the flags into strings for easier comparision + QSet allowedContent; + if (allowedConstraints & SchemaType::RestrictionConstraint) + allowedContent.insert(QString::fromLatin1("restriction")); + if (allowedConstraints & SchemaType::ExtensionConstraint) + allowedContent.insert(QString::fromLatin1("extension")); + if (allowedConstraints & SchemaType::ListConstraint) + allowedContent.insert(QString::fromLatin1("list")); + if (allowedConstraints & SchemaType::UnionConstraint) + allowedContent.insert(QString::fromLatin1("union")); + + // read content from the attribute if available, otherwise use the default definitions from the schema tag + QString content; + if (hasAttribute(QString::fromLatin1("final"))) { + content = readAttribute(QString::fromLatin1("final")); + + // split string into list to validate the content of the attribute + const QStringList values = content.split(QLatin1Char(' '), QString::SkipEmptyParts); + for (int i = 0; i < values.count(); i++) { + const QString value = values.at(i); + if (!allowedContent.contains(value) && (value != QString::fromLatin1("#all"))) { + attributeContentError("final", elementName, value); + return SchemaType::DerivationConstraints(); + } + + if ((value == QString::fromLatin1("#all")) && values.count() != 1) { + error(QtXmlPatterns::tr("%1 attribute of %2 element must either contain %3 or the other values") + .arg(formatAttribute("final")) + .arg(formatElement(elementName)) + .arg(formatData("#all"))); + return SchemaType::DerivationConstraints(); + } + } + } else { + // content of the default value has been validated in parseSchema already + content = m_finalDefault; + } + + QSet contentSet = content.split(QLatin1Char(' '), QString::SkipEmptyParts).toSet(); + + // if the '#all' tag is defined, we return all allowed values + if (contentSet.contains(QString::fromLatin1("#all"))) { + return allowedConstraints; + } else { // return the values from content set that intersects with the allowed values + contentSet.intersect(allowedContent); + + SchemaType::DerivationConstraints constraints; + + if (contentSet.contains(QString::fromLatin1("restriction"))) + constraints |= SchemaType::RestrictionConstraint; + if (contentSet.contains(QString::fromLatin1("extension"))) + constraints |= SchemaType::ExtensionConstraint; + if (contentSet.contains(QString::fromLatin1("list"))) + constraints |= SchemaType::ListConstraint; + if (contentSet.contains(QString::fromLatin1("union"))) + constraints |= SchemaType::UnionConstraint; + + return constraints; + } +} + +NamedSchemaComponent::BlockingConstraints XsdSchemaParser::readBlockingConstraintAttribute(const NamedSchemaComponent::BlockingConstraints &allowedConstraints, const char *elementName) +{ + // first convert the flags into strings for easier comparision + QSet allowedContent; + if (allowedConstraints & NamedSchemaComponent::RestrictionConstraint) + allowedContent.insert(QString::fromLatin1("restriction")); + if (allowedConstraints & NamedSchemaComponent::ExtensionConstraint) + allowedContent.insert(QString::fromLatin1("extension")); + if (allowedConstraints & NamedSchemaComponent::SubstitutionConstraint) + allowedContent.insert(QString::fromLatin1("substitution")); + + // read content from the attribute if available, otherwise use the default definitions from the schema tag + QString content; + if (hasAttribute(QString::fromLatin1("block"))) { + content = readAttribute(QString::fromLatin1("block")); + + // split string into list to validate the content of the attribute + const QStringList values = content.split(QLatin1Char(' '), QString::SkipEmptyParts); + for (int i = 0; i < values.count(); i++) { + const QString value = values.at(i); + if (!allowedContent.contains(value) && (value != QString::fromLatin1("#all"))) { + attributeContentError("block", elementName, value); + return NamedSchemaComponent::BlockingConstraints(); + } + + if ((value == QString::fromLatin1("#all")) && values.count() != 1) { + error(QtXmlPatterns::tr("%1 attribute of %2 element must either contain %3 or the other values") + .arg(formatAttribute("block")) + .arg(formatElement(elementName)) + .arg(formatData("#all"))); + return NamedSchemaComponent::BlockingConstraints(); + } + } + } else { + // content of the default value has been validated in parseSchema already + content = m_blockDefault; + } + + QSet contentSet = content.split(QLatin1Char(' '), QString::SkipEmptyParts).toSet(); + + // if the '#all' tag is defined, we return all allowed values + if (contentSet.contains(QString::fromLatin1("#all"))) { + return allowedConstraints; + } else { // return the values from content set that intersects with the allowed values + contentSet.intersect(allowedContent); + + NamedSchemaComponent::BlockingConstraints constraints; + + if (contentSet.contains(QString::fromLatin1("restriction"))) + constraints |= NamedSchemaComponent::RestrictionConstraint; + if (contentSet.contains(QString::fromLatin1("extension"))) + constraints |= NamedSchemaComponent::ExtensionConstraint; + if (contentSet.contains(QString::fromLatin1("substitution"))) + constraints |= NamedSchemaComponent::SubstitutionConstraint; + + return constraints; + } +} + +XsdXPathExpression::Ptr XsdSchemaParser::readXPathExpression(const char *elementName) +{ + const XsdXPathExpression::Ptr expression(new XsdXPathExpression()); + + const QList namespaceBindings = m_namespaceSupport.namespaceBindings(); + QXmlName emptyName; + for (int i = 0; i < namespaceBindings.count(); ++i) { + if (namespaceBindings.at(i).prefix() == StandardPrefixes::empty) + emptyName = namespaceBindings.at(i); + } + + expression->setNamespaceBindings(namespaceBindings); + + QString xpathDefaultNamespace; + if (hasAttribute(QString::fromLatin1("xpathDefaultNamespace"))) { + xpathDefaultNamespace = readAttribute(QString::fromLatin1("xpathDefaultNamespace")); + if (xpathDefaultNamespace != QString::fromLatin1("##defaultNamespace") && + xpathDefaultNamespace != QString::fromLatin1("##targetNamespace") && + xpathDefaultNamespace != QString::fromLatin1("##local")) { + if (!isValidUri(xpathDefaultNamespace)) { + attributeContentError("xpathDefaultNamespace", elementName, xpathDefaultNamespace, BuiltinTypes::xsAnyURI); + return expression; + } + } + } else { + xpathDefaultNamespace = m_xpathDefaultNamespace; + } + + AnyURI::Ptr namespaceURI; + if (xpathDefaultNamespace == QString::fromLatin1("##defaultNamespace")) { + if (!emptyName.isNull()) + namespaceURI = AnyURI::fromLexical(m_namePool->stringForNamespace(emptyName.namespaceURI())); + } else if (xpathDefaultNamespace == QString::fromLatin1("##targetNamespace")) { + if (!m_targetNamespace.isEmpty()) + namespaceURI = AnyURI::fromLexical(m_targetNamespace); + } else if (xpathDefaultNamespace == QString::fromLatin1("##local")) { + // it is absent + } else { + namespaceURI = AnyURI::fromLexical(xpathDefaultNamespace); + } + if (namespaceURI) { + if (namespaceURI->hasError()) { + attributeContentError("xpathDefaultNamespace", elementName, xpathDefaultNamespace, BuiltinTypes::xsAnyURI); + return expression; + } + + expression->setDefaultNamespace(namespaceURI); + } + + //TODO: read the base uri if qmaintaining reader support it + + return expression; +} + +QString XsdSchemaParser::readXPathAttribute(const QString &attributeName, XPathType type, const char *elementName) +{ + const QString value = readAttribute(attributeName); + if (value.isEmpty() || value.startsWith(QLatin1Char('/'))) { + attributeContentError(attributeName.toLatin1(), elementName, value); + return QString(); + } + + QXmlNamePool namePool(m_namePool.data()); + + QXmlQuery::QueryLanguage language; + switch (type) { + case XPath20: language = QXmlQuery::XPath20; break; + case XPathSelector: language = QXmlQuery::XmlSchema11IdentityConstraintSelector; break; + case XPathField: language = QXmlQuery::XmlSchema11IdentityConstraintField; break; + }; + + QXmlQuery query(language, namePool); + QXmlQueryPrivate *queryPrivate = query.d; + + const QList namespaceBindings = m_namespaceSupport.namespaceBindings(); + for (int i = 0; i < namespaceBindings.count(); ++i) { + if (!namespaceBindings.at(i).prefix() == StandardPrefixes::empty) + queryPrivate->addAdditionalNamespaceBinding(namespaceBindings.at(i)); + } + + query.setQuery(value, m_documentURI); + if (!query.isValid()) { + attributeContentError(attributeName.toLatin1(), elementName, value); + return QString(); + } + + return value; +} + +void XsdSchemaParser::validateIdAttribute(const char *elementName) +{ + if (hasAttribute(QString::fromLatin1("id"))) { + const QString value = readAttribute(QString::fromLatin1("id")); + DerivedString::Ptr id = DerivedString::fromLexical(m_namePool, value); + if (id->hasError()) { + attributeContentError("id", elementName, value, BuiltinTypes::xsID); + } else { + if (m_idCache->hasId(value)) { + error(QtXmlPatterns::tr("component with id %1 has been defined previously").arg(formatData(value))); + } else { + m_idCache->addId(value); + } + } + } +} + +bool XsdSchemaParser::isSchemaTag(XsdSchemaToken::NodeName tag, XsdSchemaToken::NodeName token, XsdSchemaToken::NodeName namespaceToken) const +{ + return ((tag == token) && (namespaceToken == XsdSchemaToken::XML_NS_SCHEMA_URI)); +} + +void XsdSchemaParser::addElement(const XsdElement::Ptr &element) +{ + const QXmlName objectName = element->name(m_namePool); + if (m_schema->element(objectName)) { + error(QtXmlPatterns::tr("element %1 already defined").arg(formatElement(m_namePool->displayName(objectName)))); + } else { + m_schema->addElement(element); + m_componentLocationHash.insert(element, currentSourceLocation()); + } +} + +void XsdSchemaParser::addAttribute(const XsdAttribute::Ptr &attribute) +{ + const QXmlName objectName = attribute->name(m_namePool); + if (m_schema->attribute(objectName)) { + error(QtXmlPatterns::tr("attribute %1 already defined").arg(formatAttribute(m_namePool->displayName(objectName)))); + } else { + m_schema->addAttribute(attribute); + m_componentLocationHash.insert(attribute, currentSourceLocation()); + } +} + +void XsdSchemaParser::addType(const SchemaType::Ptr &type) +{ + // we don't import redefinitions of builtin types, that just causes problems + if (m_builtinTypeNames.contains(type->name(m_namePool))) + return; + + const QXmlName objectName = type->name(m_namePool); + if (m_schema->type(objectName)) { + error(QtXmlPatterns::tr("type %1 already defined").arg(formatType(m_namePool, objectName))); + } else { + m_schema->addType(type); + if (type->isSimpleType()) + m_componentLocationHash.insert(XsdSimpleType::Ptr(type), currentSourceLocation()); + else + m_componentLocationHash.insert(XsdComplexType::Ptr(type), currentSourceLocation()); + } +} + +void XsdSchemaParser::addAnonymousType(const SchemaType::Ptr &type) +{ + m_schema->addAnonymousType(type); + if (type->isSimpleType()) + m_componentLocationHash.insert(XsdSimpleType::Ptr(type), currentSourceLocation()); + else + m_componentLocationHash.insert(XsdComplexType::Ptr(type), currentSourceLocation()); +} + +void XsdSchemaParser::addAttributeGroup(const XsdAttributeGroup::Ptr &group) +{ + const QXmlName objectName = group->name(m_namePool); + if (m_schema->attributeGroup(objectName)) { + error(QtXmlPatterns::tr("attribute group %1 already defined").arg(formatKeyword(m_namePool, objectName))); + } else { + m_schema->addAttributeGroup(group); + m_componentLocationHash.insert(group, currentSourceLocation()); + } +} + +void XsdSchemaParser::addElementGroup(const XsdModelGroup::Ptr &group) +{ + const QXmlName objectName = group->name(m_namePool); + if (m_schema->elementGroup(objectName)) { + error(QtXmlPatterns::tr("element group %1 already defined").arg(formatKeyword(m_namePool, objectName))); + } else { + m_schema->addElementGroup(group); + m_componentLocationHash.insert(group, currentSourceLocation()); + } +} + +void XsdSchemaParser::addNotation(const XsdNotation::Ptr ¬ation) +{ + const QXmlName objectName = notation->name(m_namePool); + if (m_schema->notation(objectName)) { + error(QtXmlPatterns::tr("notation %1 already defined").arg(formatKeyword(m_namePool, objectName))); + } else { + m_schema->addNotation(notation); + m_componentLocationHash.insert(notation, currentSourceLocation()); + } +} + +void XsdSchemaParser::addIdentityConstraint(const XsdIdentityConstraint::Ptr &constraint) +{ + const QXmlName objectName = constraint->name(m_namePool); + if (m_schema->identityConstraint(objectName)) { + error(QtXmlPatterns::tr("identity constraint %1 already defined").arg(formatKeyword(m_namePool, objectName))); + } else { + m_schema->addIdentityConstraint(constraint); + m_componentLocationHash.insert(constraint, currentSourceLocation()); + } +} + +void XsdSchemaParser::addFacet(const XsdFacet::Ptr &facet, XsdFacet::Hash &facets, const SchemaType::Ptr &type) +{ + // @see http://www.w3.org/TR/xmlschema-2/#src-single-facet-value + if (facets.contains(facet->type())) { + error(QtXmlPatterns::tr("duplicated facets in simple type %1").arg(formatType(m_namePool, type))); + return; + } + + facets.insert(facet->type(), facet); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdschemaparser_p.h b/src/xmlpatterns/schema/qxsdschemaparser_p.h new file mode 100644 index 0000000..960fb86 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdschemaparser_p.h @@ -0,0 +1,691 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdSchemaParser_H +#define Patternist_XsdSchemaParser_H + +#include "qnamespacesupport_p.h" +#include "qxsdalternative_p.h" +#include "qxsdattribute_p.h" +#include "qxsdattributegroup_p.h" +#include "qxsdattributeterm_p.h" +#include "qxsdcomplextype_p.h" +#include "qxsdelement_p.h" +#include "qxsdidcache_p.h" +#include "qxsdmodelgroup_p.h" +#include "qxsdnotation_p.h" +#include "qxsdsimpletype_p.h" +#include "qxsdschemacontext_p.h" +#include "qxsdschemaparsercontext_p.h" +#include "qxsdstatemachine_p.h" + +#include +#include +#include +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Implements the parsing of XML schema file. + * + * This class parses a XML schema in XML presentation from an QIODevice + * and returns object representation as XsdSchema. + * + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdSchemaParser : public MaintainingReader + { + friend class ElementNamespaceHandler; + friend class TagValidationHandler; + + public: + enum ParserType + { + TopLevelParser, + IncludeParser, + ImportParser, + RedefineParser + }; + + /** + * Creates a new schema parser object. + */ + XsdSchemaParser(const XsdSchemaContext::Ptr &context, const XsdSchemaParserContext::Ptr &parserContext, QIODevice *device); + + /** + * Parses the XML schema file. + * + * @return @c true on success, @c false if the schema is somehow invalid. + */ + bool parse(ParserType parserType = TopLevelParser); + + /** + * Describes a set of namespace URIs + */ + typedef QSet NamespaceSet; + + /** + * Sets which @p schemas have been included already, so the parser + * can detect circular includes. + */ + void setIncludedSchemas(const NamespaceSet &schemas); + + /** + * Sets which @p schemas have been imported already, so the parser + * can detect circular imports. + */ + void setImportedSchemas(const NamespaceSet &schemas); + + /** + * Sets which @p schemas have been redefined already, so the parser + * can detect circular redefines. + */ + void setRedefinedSchemas(const NamespaceSet &schemas); + + /** + * Sets the target namespace of the schema to parse. + */ + void setTargetNamespace(const QString &targetNamespace); + + /** + * Sets the document URI of the schema to parse. + */ + void setDocumentURI(const QUrl &uri); + + /** + * Returns the document URI of the schema to parse. + */ + QUrl documentURI() const; + + /** + * Reimplemented from MaintainingReader, always returns @c false. + */ + bool isAnyAttributeAllowed() const; + + private: + /** + * Used internally to report any kind of parsing error or + * schema inconsistency. + */ + virtual void error(const QString &msg); + + void attributeContentError(const char *attributeName, const char *elementName, const QString &value, const SchemaType::Ptr &type = SchemaType::Ptr()); + + /** + * Sets the target namespace of the schema to parse. + */ + void setTargetNamespaceExtended(const QString &targetNamespace); + + /** + * This method is called for parsing the top-level schema object. + */ + void parseSchema(ParserType parserType); + + /** + * This method is called for parsing any top-level include object. + */ + void parseInclude(); + + /** + * This method is called for parsing any top-level import object. + */ + void parseImport(); + + /** + * This method is called for parsing any top-level redefine object. + */ + void parseRedefine(); + + /** + * This method is called for parsing any annotation object everywhere + * in the schema. + */ + XsdAnnotation::Ptr parseAnnotation(); + + /** + * This method is called for parsing an appinfo object as child of + * an annotation object. + */ + XsdApplicationInformation::Ptr parseAppInfo(); + + /** + * This method is called for parsing a documentation object as child of + * an annotation object. + */ + XsdDocumentation::Ptr parseDocumentation(); + + /** + * This method is called for parsing a defaultOpenContent object. + */ + void parseDefaultOpenContent(); + + /** + * This method is called for parsing any top-level simpleType object. + */ + XsdSimpleType::Ptr parseGlobalSimpleType(); + + /** + * This method is called for parsing any simpleType object as descendant + * of an element or complexType object. + */ + XsdSimpleType::Ptr parseLocalSimpleType(); + + /** + * This method is called for parsing a restriction object as child + * of a simpleType object. + */ + void parseSimpleRestriction(const XsdSimpleType::Ptr &ptr); + + /** + * This method is called for parsing a list object as child + * of a simpleType object. + */ + void parseList(const XsdSimpleType::Ptr &ptr); + + /** + * This method is called for parsing a union object as child + * of a simpleType object. + */ + void parseUnion(const XsdSimpleType::Ptr &ptr); + + /** + * This method is called for parsing a minExclusive object as child + * of a restriction object. + */ + XsdFacet::Ptr parseMinExclusiveFacet(); + + /** + * This method is called for parsing a minInclusive object as child + * of a restriction object. + */ + XsdFacet::Ptr parseMinInclusiveFacet(); + + /** + * This method is called for parsing a maxExclusive object as child + * of a restriction object. + */ + XsdFacet::Ptr parseMaxExclusiveFacet(); + + /** + * This method is called for parsing a maxInclusive object as child + * of a restriction object. + */ + XsdFacet::Ptr parseMaxInclusiveFacet(); + + /** + * This method is called for parsing a totalDigits object as child + * of a restriction object. + */ + XsdFacet::Ptr parseTotalDigitsFacet(); + + /** + * This method is called for parsing a fractionDigits object as child + * of a restriction object. + */ + XsdFacet::Ptr parseFractionDigitsFacet(); + + /** + * This method is called for parsing a length object as child + * of a restriction object. + */ + XsdFacet::Ptr parseLengthFacet(); + + /** + * This method is called for parsing a minLength object as child + * of a restriction object. + */ + XsdFacet::Ptr parseMinLengthFacet(); + + /** + * This method is called for parsing a maxLength object as child + * of a restriction object. + */ + XsdFacet::Ptr parseMaxLengthFacet(); + + /** + * This method is called for parsing an enumeration object as child + * of a restriction object. + */ + XsdFacet::Ptr parseEnumerationFacet(); + + /** + * This method is called for parsing a whiteSpace object as child + * of a restriction object. + */ + XsdFacet::Ptr parseWhiteSpaceFacet(); + + /** + * This method is called for parsing a pattern object as child + * of a restriction object. + */ + XsdFacet::Ptr parsePatternFacet(); + + /** + * This method is called for parsing an assertion object as child + * of a restriction object. + */ + XsdFacet::Ptr parseAssertionFacet(); + + /** + * This method is called for parsing any top-level complexType object. + */ + XsdComplexType::Ptr parseGlobalComplexType(); + + /** + * This method is called for parsing any complexType object as descendant + * of an element object. + */ + XsdComplexType::Ptr parseLocalComplexType(); + + /** + * This method resolves the content type of the @p complexType for the given + * @p effectiveMixed value. + */ + void resolveComplexContentType(const XsdComplexType::Ptr &complexType, bool effectiveMixed); + + /** + * This method is called for parsing a simpleContent object as child + * of a complexType object. + */ + void parseSimpleContent(const XsdComplexType::Ptr &complexType); + + /** + * This method is called for parsing a restriction object as child + * of a simpleContent object. + */ + void parseSimpleContentRestriction(const XsdComplexType::Ptr &complexType); + + /** + * This method is called for parsing an extension object as child + * of a simpleContent object. + */ + void parseSimpleContentExtension(const XsdComplexType::Ptr &complexType); + + /** + * This method is called for parsing a complexContent object as child + * of a complexType object. + * + * @param complexType The complex type the complex content belongs to. + * @param mixed The output parameter for the mixed value. + */ + void parseComplexContent(const XsdComplexType::Ptr &complexType, bool *mixed); + + /** + * This method is called for parsing a restriction object as child + * of a complexContent object. + */ + void parseComplexContentRestriction(const XsdComplexType::Ptr &complexType); + + /** + * This method is called for parsing an extension object as child + * of a complexContent object. + */ + void parseComplexContentExtension(const XsdComplexType::Ptr &complexType); + + /** + * This method is called for parsing an assert object as child + * of a complexType or parsing a assertion facet object as + * child of a simpleType. + * + * @param nodeName Either XsdSchemaToken::Assert or XsdSchemaToken::Assertion. + * @param tag Either XsdTagScope::Assert or XsdTagScope::Assertion. + */ + XsdAssertion::Ptr parseAssertion(const XsdSchemaToken::NodeName &nodeName, const XsdTagScope::Type &tag); + + /** + * This method is called for parsing an openContent object. + */ + XsdComplexType::OpenContent::Ptr parseOpenContent(); + + /** + * This method is called for parsing a top-level group object. + */ + XsdModelGroup::Ptr parseNamedGroup(); + + /** + * This method is called for parsing a non-top-level group object + * that contains a ref attribute. + */ + XsdTerm::Ptr parseReferredGroup(const XsdParticle::Ptr &particle); + + /** + * This method is called for parsing an all object as child + * of a top-level group object. + * + * @param parent The schema component the all object is part of. + */ + XsdModelGroup::Ptr parseAll(const NamedSchemaComponent::Ptr &parent); + + /** + * This method is called for parsing an all object as descendant + * of a complexType object. + * + * @param particle The particle the all object belongs to. + * @param parent The schema component the all object is part of. + */ + XsdModelGroup::Ptr parseLocalAll(const XsdParticle::Ptr &particle, const NamedSchemaComponent::Ptr &parent); + + /** + * This method is called for parsing a choice object as child + * of a top-level group object. + * + * @param parent The schema component the choice object is part of. + */ + XsdModelGroup::Ptr parseChoice(const NamedSchemaComponent::Ptr &parent); + + /** + * This method is called for parsing a choice object as descendant + * of a complexType object or a choice object. + * + * @param particle The particle the choice object belongs to. + * @param parent The schema component the choice object is part of. + */ + XsdModelGroup::Ptr parseLocalChoice(const XsdParticle::Ptr &particle, const NamedSchemaComponent::Ptr &parent); + + /** + * This method is called for parsing a sequence object as child + * of a top-level group object. + * + * @param parent The schema component the sequence object is part of. + */ + XsdModelGroup::Ptr parseSequence(const NamedSchemaComponent::Ptr &parent); + + /** + * This method is called for parsing a sequence object as descendant + * of a complexType object or a sequence object. + * + * @param particle The particle the sequence object belongs to. + * @param parent The schema component the sequence object is part of. + */ + XsdModelGroup::Ptr parseLocalSequence(const XsdParticle::Ptr &particle, const NamedSchemaComponent::Ptr &parent); + + /** + * A helper method that parses the minOccurs and maxOccurs constraints for + * the given @p particle that has the given @p tagName. + */ + bool parseMinMaxConstraint(const XsdParticle::Ptr &particle, const char* tagName); + + /** + * This method is called for parsing any top-level attribute object. + */ + XsdAttribute::Ptr parseGlobalAttribute(); + + /** + * This method is called for parsing any non-top-level attribute object as a + * descendant of a complexType object or an attributeGroup object. + * + * @param parent The parent component the attribute object is part of. + */ + XsdAttributeUse::Ptr parseLocalAttribute(const NamedSchemaComponent::Ptr &parent); + + /** + * This method is called for parsing a top-level attributeGroup object. + */ + XsdAttributeGroup::Ptr parseNamedAttributeGroup(); + + /** + * This method is called for parsing a non-top-level attributeGroup object + * that contains a ref attribute. + */ + XsdAttributeUse::Ptr parseReferredAttributeGroup(); + + /** + * This method is called for parsing any top-level element object. + */ + XsdElement::Ptr parseGlobalElement(); + + /** + * This method is called for parsing any non-top-level element object as a + * descendant of a complexType object or a group object. + * + * @param particle The particle the element object belongs to. + * @param parent The parent component the element object is part of. + */ + XsdTerm::Ptr parseLocalElement(const XsdParticle::Ptr &particle, const NamedSchemaComponent::Ptr &parent); + + /** + * This method is called for parsing a unique object as child of an element object. + */ + XsdIdentityConstraint::Ptr parseUnique(); + + /** + * This method is called for parsing a key object as child of an element object. + */ + XsdIdentityConstraint::Ptr parseKey(); + + /** + * This method is called for parsing a keyref object as child of an element object. + */ + XsdIdentityConstraint::Ptr parseKeyRef(const XsdElement::Ptr &element); + + /** + * This method is called for parsing a selector object as child of an unique object, + * key object or keyref object, + * + * @param ptr The identity constraint it belongs to. + */ + void parseSelector(const XsdIdentityConstraint::Ptr &ptr); + + /** + * This method is called for parsing a field object as child of an unique object, + * key object or keyref object, + * + * @param ptr The identity constraint it belongs to. + */ + void parseField(const XsdIdentityConstraint::Ptr &ptr); + + /** + * This method is called for parsing an alternative object inside an element object. + */ + XsdAlternative::Ptr parseAlternative(); + + /** + * This method is called for parsing a top-level notation object. + */ + XsdNotation::Ptr parseNotation(); + + /** + * This method is called for parsing an any object somewhere in + * the schema. + * + * @param particle The particle the any object belongs to. + */ + XsdWildcard::Ptr parseAny(const XsdParticle::Ptr &particle); + + /** + * This method is called for parsing an anyAttribute object somewhere in + * the schema. + */ + XsdWildcard::Ptr parseAnyAttribute(); + + /** + * This method is called for parsing unknown object as descendant of the annotation object. + */ + void parseUnknownDocumentation(); + + /** + * This method is called for parsing unknown object in the schema. + */ + void parseUnknown(); + + /** + * Returnes an source location for the current position. + */ + QSourceLocation currentSourceLocation() const; + + /** + * Converts a @p qualified name into a QXmlName @p name and does some error handling. + */ + void convertName(const QString &qualified, NamespaceSupport::NameType type, QXmlName &name); + + /** + * A helper method that reads in a 'name' attribute and checks it for syntactic errors. + */ + inline QString readNameAttribute(const char *elementName); + + /** + * A helper method that reads in an attribute that contains an QName and + * checks it for syntactic errors. + */ + inline QString readQNameAttribute(const QString &typeAttribute, const char *elementName); + + /** + * A helper method that reads in a namespace attribute and checks for syntactic errors. + */ + inline QString readNamespaceAttribute(const QString &attributeName, const char *elementName); + + /** + * A helper method that reads the final attribute and does correct handling of schema default definitions. + */ + inline SchemaType::DerivationConstraints readDerivationConstraintAttribute(const SchemaType::DerivationConstraints &allowedConstraints, const char *elementName); + + /** + * A helper method that reads the block attribute and does correct handling of schema default definitions. + */ + inline NamedSchemaComponent::BlockingConstraints readBlockingConstraintAttribute(const NamedSchemaComponent::BlockingConstraints &allowedConstraints, const char *elementName); + + /** + * A helper method that reads all components for a xpath expression for the current scope. + */ + XsdXPathExpression::Ptr readXPathExpression(const char *elementName); + + /** + * Describes the type of XPath that is allowed by the readXPathAttribute method. + */ + enum XPathType { + XPath20, + XPathSelector, + XPathField + }; + + /** + * A helper method that reads an attribute that represents a xpath query and does basic + * validation. + */ + QString readXPathAttribute(const QString &attributeName, XPathType type, const char *elementName); + + /** + * A helper method that reads in an "id" attribute, checks it for syntactic errors + * and tests whether a component with the same id has already been parsed. + */ + inline void validateIdAttribute(const char *elementName); + + /** + * Adds an @p element to the schema and checks for duplicated entries. + */ + void addElement(const XsdElement::Ptr &element); + + /** + * Adds an @p attribute to the schema and checks for duplicated entries. + */ + void addAttribute(const XsdAttribute::Ptr &attribute); + + /** + * Adds a @p type to the schema and checks for duplicated entries. + */ + void addType(const SchemaType::Ptr &type); + + /** + * Adds an anonymous @p type to the schema and checks for duplicated entries. + */ + void addAnonymousType(const SchemaType::Ptr &type); + + /** + * Adds an attribute @p group to the schema and checks for duplicated entries. + */ + void addAttributeGroup(const XsdAttributeGroup::Ptr &group); + + /** + * Adds an element @p group to the schema and checks for duplicated entries. + */ + void addElementGroup(const XsdModelGroup::Ptr &group); + + /** + * Adds a @p notation to the schema and checks for duplicated entries. + */ + void addNotation(const XsdNotation::Ptr ¬ation); + + /** + * Adds an identity @p constraint to the schema and checks for duplicated entries. + */ + void addIdentityConstraint(const XsdIdentityConstraint::Ptr &constraint); + + /** + * Adds the @p facet to the list of @p facets for @p type and checks for duplicates. + */ + void addFacet(const XsdFacet::Ptr &facet, XsdFacet::Hash &facets, const SchemaType::Ptr &type); + + /** + * Sets up the state machines for validating the right occurrence of xml elements. + */ + void setupStateMachines(); + + /** + * Sets up a list of names of known builtin types. + */ + void setupBuiltinTypeNames(); + + /** + * Checks whether the given @p tag is equal to the given @p token and + * the given @p namespaceToken is the XML Schema namespace. + */ + inline bool isSchemaTag(XsdSchemaToken::NodeName tag, XsdSchemaToken::NodeName token, XsdSchemaToken::NodeName namespaceToken) const; + + XsdSchemaContext::Ptr m_context; + XsdSchemaParserContext::Ptr m_parserContext; + NamePool::Ptr m_namePool; + NamespaceSupport m_namespaceSupport; + XsdSchemaResolver::Ptr m_schemaResolver; + XsdSchema::Ptr m_schema; + + QString m_targetNamespace; + QString m_attributeFormDefault; + QString m_elementFormDefault; + QString m_blockDefault; + QString m_finalDefault; + QString m_xpathDefaultNamespace; + QXmlName m_defaultAttributes; + XsdComplexType::OpenContent::Ptr m_defaultOpenContent; + bool m_defaultOpenContentAppliesToEmpty; + + NamespaceSet m_includedSchemas; + NamespaceSet m_importedSchemas; + NamespaceSet m_redefinedSchemas; + QUrl m_documentURI; + XsdIdCache::Ptr m_idCache; + QHash > m_stateMachines; + ComponentLocationHash m_componentLocationHash; + QSet m_builtinTypeNames; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsdschemaparser_setup.cpp b/src/xmlpatterns/schema/qxsdschemaparser_setup.cpp new file mode 100644 index 0000000..167af7a --- /dev/null +++ b/src/xmlpatterns/schema/qxsdschemaparser_setup.cpp @@ -0,0 +1,1070 @@ + +#include "qxsdschemaparser_p.h" + +#include "qbuiltintypes_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +/** + * @page using_dfa_for_schema Using DFA for validation of correct XML tag occurrence + * + * This page describes how to use DFAs for validating that the XML child tags of an + * XML parent tag occur in the right order. + * + * To validate the occurence of XML tags one need a regular expression that describes + * which tags can appear how often in what context. For example the regular expression + * of the global attribute tag in XML Schema is (annotation?, simpleType?). + * That means the attribute tag can contain an annotation tag followed + * by a simpleType tag, or just one simpleType tag and even no child + * tag at all. + * So the regular expression describes some kind of language and all the various occurrences + * of the child tags can be seen as words of that language. + * We can create a DFA now, that accepts all words (and only these words) of that language + * and whenever we want to check if a sequence of child tags belongs to the language, + * we test if the sequence passes the DFA successfully. + * + * The following example shows how to create the DFA for the regular expression method + * above. + * + * \dotfile GlobalAttribute_diagram.dot + * + * At first we need a start state (1), that's the state the DFA is before it + * starts running. As our regular expression allows that there are no child tags, the + * start state is an end state as well (marked by the double circle). + * Now we fetch the first token from the XML file (let's assume it is an annotation tag) + * and check if there is an edge labled with the tag name leaving the current state of the DFA. + * If there is no such edge, the input doesn't fullfill the rules of the regular expression, + * so we throw an error. Otherwise we follow that edge and the DFA is set to the new state (2) the + * edge points to. Now we fetch the next token from the XML file and do the previous steps again. + * If there is no further input from the XML file, we check whether the DFA is in an end state and + * throw an error if not. + * + * So the algorithm for checking is quite simple, the whole logic is encoded in the DFA and creating + * one for a regular expression is sometimes not easy, however the ones for XML Schema are straight + * forward. + * + *

Legend:

+ * \dotfile legend.dot + *
+ * + *

DFA for all tag

+ * \dotfile All_diagram.dot + *
+ *

DFA for alternative tag

+ * \dotfile Alternative_diagram.dot + *
+ *

DFA for annotation tag

+ * \dotfile Annotation_diagram.dot + *
+ *

DFA for anyAttribute tag

+ * \dotfile AnyAttribute_diagram.dot + *
+ *

DFA for any tag

+ * \dotfile Any_diagram.dot + *
+ *

DFA for assert tag

+ * \dotfile Assert_diagram.dot + *
+ *

DFA for choice tag

+ * \dotfile Choice_diagram.dot + *
+ *

DFA for complexContent tag

+ * \dotfile ComplexContent_diagram.dot + *
+ *

DFA for extension tag inside a complexContent tag

+ * \dotfile ComplexContentExtension_diagram.dot + *
+ *

DFA for restriction tag inside a complexContent tag

+ * \dotfile ComplexContentRestriction_diagram.dot + *
+ *

DFA for defaultOpenContent tag

+ * \dotfile DefaultOpenContent_diagram.dot + *
+ *

DFA for enumeration tag

+ * \dotfile EnumerationFacet_diagram.dot + *
+ *

DFA for field tag

+ * \dotfile Field_diagram.dot + *
+ *

DFA for fractionDigits tag

+ * \dotfile FractionDigitsFacet_diagram.dot + *
+ *

DFA for attribute tag

+ * \dotfile GlobalAttribute_diagram.dot + *
+ *

DFA for complexType tag

+ * \dotfile GlobalComplexType_diagram.dot + *
+ *

DFA for element tag

+ * \dotfile GlobalElement_diagram.dot + *
+ *

DFA for simpleType tag

+ * \dotfile GlobalSimpleType_diagram.dot + *
+ *

DFA for import tag

+ * \dotfile Import_diagram.dot + *
+ *

DFA for include tag

+ * \dotfile Include_diagram.dot + *
+ *

DFA for key tag

+ * \dotfile Key_diagram.dot + *
+ *

DFA for keyref tag

+ * \dotfile KeyRef_diagram.dot + *
+ *

DFA for length tag

+ * \dotfile LengthFacet_diagram.dot + *
+ *

DFA for list tag

+ * \dotfile List_diagram.dot + *
+ *

DFA for all tag

+ * \dotfile LocalAll_diagram.dot + *
+ *

DFA for attribute tag

+ * \dotfile LocalAttribute_diagram.dot + *
+ *

DFA for choice tag

+ * \dotfile LocalChoice_diagram.dot + *
+ *

DFA for complexType tag

+ * \dotfile LocalComplexType_diagram.dot + *
+ *

DFA for element tag

+ * \dotfile LocalElement_diagram.dot + *
+ *

DFA for sequence tag

+ * \dotfile LocalSequence_diagram.dot + *
+ *

DFA for simpleType tag that

+ * \dotfile LocalSimpleType_diagram.dot + *
+ *

DFA for maxExclusive tag

+ * \dotfile MaxExclusiveFacet_diagram.dot + *
+ *

DFA for maxInclusive tag

+ * \dotfile MaxInclusiveFacet_diagram.dot + *
+ *

DFA for maxLength tag

+ * \dotfile MaxLengthFacet_diagram.dot + *
+ *

DFA for minExclusive tag

+ * \dotfile MinExclusiveFacet_diagram.dot + *
+ *

DFA for minInclusive tag

+ * \dotfile MinInclusiveFacet_diagram.dot + *
+ *

DFA for minLength tag

+ * \dotfile MinLengthFacet_diagram.dot + *
+ *

DFA for attributeGroup tag without ref attribute

+ * \dotfile NamedAttributeGroup_diagram.dot + *
+ *

DFA for group tag without ref attribute

+ * \dotfile NamedGroup_diagram.dot + *
+ *

DFA for notation tag

+ * \dotfile Notation_diagram.dot + *
+ *

DFA for override tag

+ * \dotfile Override_diagram.dot + *
+ *

DFA for pattern tag

+ * \dotfile PatternFacet_diagram.dot + *
+ *

DFA for redefine tag

+ * \dotfile Redefine_diagram.dot + *
+ *

DFA for attributeGroup tag with ref attribute

+ * \dotfile ReferredAttributeGroup_diagram.dot + *
+ *

DFA for group tag with ref attribute

+ * \dotfile ReferredGroup_diagram.dot + *
+ *

DFA for schema tag

+ * \dotfile Schema_diagram.dot + *
+ *

DFA for selector tag

+ * \dotfile Selector_diagram.dot + *
+ *

DFA for sequence tag

+ * \dotfile Sequence_diagram.dot + *
+ *

DFA for simpleContent tag

+ * \dotfile SimpleContent_diagram.dot + *
+ *

DFA for extension tag inside a simpleContent tag

+ * \dotfile SimpleContentExtension_diagram.dot + *
+ *

DFA for restriction tag inside a simpleContent tag

+ * \dotfile SimpleContentRestriction_diagram.dot + *
+ *

DFA for restriction tag inside a simpleType tag

+ * \dotfile SimpleRestriction_diagram.dot + *
+ *

DFA for totalDigits tag

+ * \dotfile TotalDigitsFacet_diagram.dot + *
+ *

DFA for union tag

+ * \dotfile Union_diagram.dot + *
+ *

DFA for unique tag

+ * \dotfile Unique_diagram.dot + *
+ *

DFA for whiteSpace tag

+ * \dotfile WhiteSpaceFacet_diagram.dot + */ + +void XsdSchemaParser::setupStateMachines() +{ + { + XsdStateMachine machine(m_namePool); + + // setup state machine for (annotation?, simpleType?) : attribute + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Annotation, s1); + machine.addTransition(startState, XsdSchemaToken::SimpleType, s2); + machine.addTransition(s1, XsdSchemaToken::SimpleType, s2); + + m_stateMachines.insert(XsdTagScope::GlobalAttribute, machine); + m_stateMachines.insert(XsdTagScope::LocalAttribute, machine); + } + + { + XsdStateMachine machine(m_namePool); + + // setup state machine for (annotation?, ((simpleType | complexType)?, alternative*, (unique | key | keyref)*)) : element + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s3 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s4 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Annotation, s1); + machine.addTransition(startState, XsdSchemaToken::SimpleType, s2); + machine.addTransition(startState, XsdSchemaToken::ComplexType, s2); + machine.addTransition(startState, XsdSchemaToken::Alternative, s3); + machine.addTransition(startState, XsdSchemaToken::Unique, s4); + machine.addTransition(startState, XsdSchemaToken::Key, s4); + machine.addTransition(startState, XsdSchemaToken::Keyref, s4); + + machine.addTransition(s1, XsdSchemaToken::SimpleType, s2); + machine.addTransition(s1, XsdSchemaToken::ComplexType, s2); + machine.addTransition(s1, XsdSchemaToken::Alternative, s3); + machine.addTransition(s1, XsdSchemaToken::Unique, s4); + machine.addTransition(s1, XsdSchemaToken::Key, s4); + machine.addTransition(s1, XsdSchemaToken::Keyref, s4); + + machine.addTransition(s2, XsdSchemaToken::Alternative, s3); + machine.addTransition(s2, XsdSchemaToken::Unique, s4); + machine.addTransition(s2, XsdSchemaToken::Key, s4); + machine.addTransition(s2, XsdSchemaToken::Keyref, s4); + + machine.addTransition(s3, XsdSchemaToken::Alternative, s3); + machine.addTransition(s3, XsdSchemaToken::Unique, s4); + machine.addTransition(s3, XsdSchemaToken::Key, s4); + machine.addTransition(s3, XsdSchemaToken::Keyref, s4); + + machine.addTransition(s4, XsdSchemaToken::Unique, s4); + machine.addTransition(s4, XsdSchemaToken::Key, s4); + machine.addTransition(s4, XsdSchemaToken::Keyref, s4); + + m_stateMachines.insert(XsdTagScope::GlobalElement, machine); + m_stateMachines.insert(XsdTagScope::LocalElement, machine); + } + + { + XsdStateMachine machine(m_namePool); + + // setup state machine for (annotation?, (simpleContent | complexContent | (openContent?, (group | all | choice | sequence)?, ((attribute | attributeGroup)*, anyAttribute?), assert*))) : complexType + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s3 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s4 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s5 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s6 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s7 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Annotation, s1); + machine.addTransition(startState, XsdSchemaToken::SimpleContent, s2); + machine.addTransition(startState, XsdSchemaToken::ComplexContent, s2); + machine.addTransition(startState, XsdSchemaToken::OpenContent, s3); + machine.addTransition(startState, XsdSchemaToken::Group, s4); + machine.addTransition(startState, XsdSchemaToken::All, s4); + machine.addTransition(startState, XsdSchemaToken::Choice, s4); + machine.addTransition(startState, XsdSchemaToken::Sequence, s4); + machine.addTransition(startState, XsdSchemaToken::Attribute, s5); + machine.addTransition(startState, XsdSchemaToken::AttributeGroup, s5); + machine.addTransition(startState, XsdSchemaToken::AnyAttribute, s6); + machine.addTransition(startState, XsdSchemaToken::Assert, s7); + + machine.addTransition(s1, XsdSchemaToken::SimpleContent, s2); + machine.addTransition(s1, XsdSchemaToken::ComplexContent, s2); + machine.addTransition(s1, XsdSchemaToken::OpenContent, s3); + machine.addTransition(s1, XsdSchemaToken::Group, s4); + machine.addTransition(s1, XsdSchemaToken::All, s4); + machine.addTransition(s1, XsdSchemaToken::Choice, s4); + machine.addTransition(s1, XsdSchemaToken::Sequence, s4); + machine.addTransition(s1, XsdSchemaToken::Attribute, s5); + machine.addTransition(s1, XsdSchemaToken::AttributeGroup, s5); + machine.addTransition(s1, XsdSchemaToken::AnyAttribute, s6); + machine.addTransition(s1, XsdSchemaToken::Assert, s7); + + machine.addTransition(s3, XsdSchemaToken::Group, s4); + machine.addTransition(s3, XsdSchemaToken::All, s4); + machine.addTransition(s3, XsdSchemaToken::Choice, s4); + machine.addTransition(s3, XsdSchemaToken::Sequence, s4); + machine.addTransition(s3, XsdSchemaToken::Attribute, s5); + machine.addTransition(s3, XsdSchemaToken::AttributeGroup, s5); + machine.addTransition(s3, XsdSchemaToken::AnyAttribute, s6); + machine.addTransition(s3, XsdSchemaToken::Assert, s7); + + machine.addTransition(s4, XsdSchemaToken::Attribute, s5); + machine.addTransition(s4, XsdSchemaToken::AttributeGroup, s5); + machine.addTransition(s4, XsdSchemaToken::AnyAttribute, s6); + machine.addTransition(s4, XsdSchemaToken::Assert, s7); + + machine.addTransition(s5, XsdSchemaToken::Attribute, s5); + machine.addTransition(s5, XsdSchemaToken::AttributeGroup, s5); + machine.addTransition(s5, XsdSchemaToken::AnyAttribute, s6); + machine.addTransition(s5, XsdSchemaToken::Assert, s7); + + machine.addTransition(s6, XsdSchemaToken::Assert, s7); + + machine.addTransition(s7, XsdSchemaToken::Assert, s7); + + m_stateMachines.insert(XsdTagScope::GlobalComplexType, machine); + m_stateMachines.insert(XsdTagScope::LocalComplexType, machine); + } + + { + XsdStateMachine machine(m_namePool); + + // setup state machine for (annotation?, (restriction | extension)) : simpleContent/complexContent + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::InternalState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Annotation, s1); + machine.addTransition(startState, XsdSchemaToken::Restriction, s2); + machine.addTransition(startState, XsdSchemaToken::Extension, s2); + + machine.addTransition(s1, XsdSchemaToken::Restriction, s2); + machine.addTransition(s1, XsdSchemaToken::Extension, s2); + + m_stateMachines.insert(XsdTagScope::SimpleContent, machine); + m_stateMachines.insert(XsdTagScope::ComplexContent, machine); + } + + { + XsdStateMachine machine(m_namePool); + + // setup state machine for (annotation?, (simpleType?, (minExclusive | minInclusive | maxExclusive | maxInclusive | totalDigits | fractionDigits | length | minLength | maxLength | enumeration | whiteSpace | pattern | assertion)*)?, ((attribute | attributeGroup)*, anyAttribute?), assert*) : simpleContent restriction + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s3 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s4 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s5 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s6 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Annotation, s1); + machine.addTransition(startState, XsdSchemaToken::SimpleType, s2); + machine.addTransition(startState, XsdSchemaToken::MinExclusive, s3); + machine.addTransition(startState, XsdSchemaToken::MinInclusive, s3); + machine.addTransition(startState, XsdSchemaToken::MaxExclusive, s3); + machine.addTransition(startState, XsdSchemaToken::MaxInclusive, s3); + machine.addTransition(startState, XsdSchemaToken::TotalDigits, s3); + machine.addTransition(startState, XsdSchemaToken::FractionDigits, s3); + machine.addTransition(startState, XsdSchemaToken::Length, s3); + machine.addTransition(startState, XsdSchemaToken::MinLength, s3); + machine.addTransition(startState, XsdSchemaToken::MaxLength, s3); + machine.addTransition(startState, XsdSchemaToken::Enumeration, s3); + machine.addTransition(startState, XsdSchemaToken::WhiteSpace, s3); + machine.addTransition(startState, XsdSchemaToken::Pattern, s3); + machine.addTransition(startState, XsdSchemaToken::Assertion, s3); + machine.addTransition(startState, XsdSchemaToken::Attribute, s4); + machine.addTransition(startState, XsdSchemaToken::AttributeGroup, s4); + machine.addTransition(startState, XsdSchemaToken::AnyAttribute, s5); + machine.addTransition(startState, XsdSchemaToken::Assert, s6); + + machine.addTransition(s1, XsdSchemaToken::SimpleType, s2); + machine.addTransition(s1, XsdSchemaToken::MinExclusive, s3); + machine.addTransition(s1, XsdSchemaToken::MinInclusive, s3); + machine.addTransition(s1, XsdSchemaToken::MaxExclusive, s3); + machine.addTransition(s1, XsdSchemaToken::MaxInclusive, s3); + machine.addTransition(s1, XsdSchemaToken::TotalDigits, s3); + machine.addTransition(s1, XsdSchemaToken::FractionDigits, s3); + machine.addTransition(s1, XsdSchemaToken::Length, s3); + machine.addTransition(s1, XsdSchemaToken::MinLength, s3); + machine.addTransition(s1, XsdSchemaToken::MaxLength, s3); + machine.addTransition(s1, XsdSchemaToken::Enumeration, s3); + machine.addTransition(s1, XsdSchemaToken::WhiteSpace, s3); + machine.addTransition(s1, XsdSchemaToken::Pattern, s3); + machine.addTransition(s1, XsdSchemaToken::Assertion, s3); + machine.addTransition(s1, XsdSchemaToken::Attribute, s4); + machine.addTransition(s1, XsdSchemaToken::AttributeGroup, s4); + machine.addTransition(s1, XsdSchemaToken::AnyAttribute, s5); + machine.addTransition(s1, XsdSchemaToken::Assert, s6); + + machine.addTransition(s2, XsdSchemaToken::MinExclusive, s3); + machine.addTransition(s2, XsdSchemaToken::MinInclusive, s3); + machine.addTransition(s2, XsdSchemaToken::MaxExclusive, s3); + machine.addTransition(s2, XsdSchemaToken::MaxInclusive, s3); + machine.addTransition(s2, XsdSchemaToken::TotalDigits, s3); + machine.addTransition(s2, XsdSchemaToken::FractionDigits, s3); + machine.addTransition(s2, XsdSchemaToken::Length, s3); + machine.addTransition(s2, XsdSchemaToken::MinLength, s3); + machine.addTransition(s2, XsdSchemaToken::MaxLength, s3); + machine.addTransition(s2, XsdSchemaToken::Enumeration, s3); + machine.addTransition(s2, XsdSchemaToken::WhiteSpace, s3); + machine.addTransition(s2, XsdSchemaToken::Pattern, s3); + machine.addTransition(s2, XsdSchemaToken::Assertion, s3); + machine.addTransition(s2, XsdSchemaToken::Attribute, s4); + machine.addTransition(s2, XsdSchemaToken::AttributeGroup, s4); + machine.addTransition(s2, XsdSchemaToken::AnyAttribute, s5); + machine.addTransition(s2, XsdSchemaToken::Assert, s6); + + machine.addTransition(s3, XsdSchemaToken::MinExclusive, s3); + machine.addTransition(s3, XsdSchemaToken::MinInclusive, s3); + machine.addTransition(s3, XsdSchemaToken::MaxExclusive, s3); + machine.addTransition(s3, XsdSchemaToken::MaxInclusive, s3); + machine.addTransition(s3, XsdSchemaToken::TotalDigits, s3); + machine.addTransition(s3, XsdSchemaToken::FractionDigits, s3); + machine.addTransition(s3, XsdSchemaToken::Length, s3); + machine.addTransition(s3, XsdSchemaToken::MinLength, s3); + machine.addTransition(s3, XsdSchemaToken::MaxLength, s3); + machine.addTransition(s3, XsdSchemaToken::Enumeration, s3); + machine.addTransition(s3, XsdSchemaToken::WhiteSpace, s3); + machine.addTransition(s3, XsdSchemaToken::Pattern, s3); + machine.addTransition(s3, XsdSchemaToken::Assertion, s3); + machine.addTransition(s3, XsdSchemaToken::Attribute, s4); + machine.addTransition(s3, XsdSchemaToken::AttributeGroup, s4); + machine.addTransition(s3, XsdSchemaToken::AnyAttribute, s5); + machine.addTransition(s3, XsdSchemaToken::Assert, s6); + + machine.addTransition(s4, XsdSchemaToken::Attribute, s4); + machine.addTransition(s4, XsdSchemaToken::AttributeGroup, s4); + machine.addTransition(s4, XsdSchemaToken::AnyAttribute, s5); + machine.addTransition(s4, XsdSchemaToken::Assert, s6); + + machine.addTransition(s5, XsdSchemaToken::Assert, s6); + + machine.addTransition(s6, XsdSchemaToken::Assert, s6); + + m_stateMachines.insert(XsdTagScope::SimpleContentRestriction, machine); + } + + { + XsdStateMachine machine(m_namePool); + + // setup state machine for (annotation?, ((attribute | attributeGroup)*, anyAttribute?), assert*) : simple content extension + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s3 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s4 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Annotation, s1); + machine.addTransition(startState, XsdSchemaToken::Attribute, s2); + machine.addTransition(startState, XsdSchemaToken::AttributeGroup, s2); + machine.addTransition(startState, XsdSchemaToken::AnyAttribute, s3); + machine.addTransition(startState, XsdSchemaToken::Assert, s4); + + machine.addTransition(s1, XsdSchemaToken::Attribute, s2); + machine.addTransition(s1, XsdSchemaToken::AttributeGroup, s2); + machine.addTransition(s1, XsdSchemaToken::AnyAttribute, s3); + machine.addTransition(s1, XsdSchemaToken::Assert, s4); + + machine.addTransition(s2, XsdSchemaToken::Attribute, s2); + machine.addTransition(s2, XsdSchemaToken::AttributeGroup, s2); + machine.addTransition(s2, XsdSchemaToken::AnyAttribute, s3); + machine.addTransition(s2, XsdSchemaToken::Assert, s4); + + machine.addTransition(s3, XsdSchemaToken::Assert, s4); + + machine.addTransition(s4, XsdSchemaToken::Assert, s4); + + m_stateMachines.insert(XsdTagScope::SimpleContentExtension, machine); + } + + { + XsdStateMachine machine(m_namePool); + + // setup state machine for (annotation?, openContent?, ((group | all | choice | sequence)?, ((attribute | attributeGroup)*, anyAttribute?), assert*)) : complex content restriction/complex content extension + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s3 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s4 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s5 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s6 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Annotation, s1); + machine.addTransition(startState, XsdSchemaToken::OpenContent, s2); + machine.addTransition(startState, XsdSchemaToken::Group, s3); + machine.addTransition(startState, XsdSchemaToken::All, s3); + machine.addTransition(startState, XsdSchemaToken::Choice, s3); + machine.addTransition(startState, XsdSchemaToken::Sequence, s3); + machine.addTransition(startState, XsdSchemaToken::Attribute, s4); + machine.addTransition(startState, XsdSchemaToken::AttributeGroup, s4); + machine.addTransition(startState, XsdSchemaToken::AnyAttribute, s5); + machine.addTransition(startState, XsdSchemaToken::Assert, s6); + + machine.addTransition(s1, XsdSchemaToken::OpenContent, s2); + machine.addTransition(s1, XsdSchemaToken::Group, s3); + machine.addTransition(s1, XsdSchemaToken::All, s3); + machine.addTransition(s1, XsdSchemaToken::Choice, s3); + machine.addTransition(s1, XsdSchemaToken::Sequence, s3); + machine.addTransition(s1, XsdSchemaToken::Attribute, s4); + machine.addTransition(s1, XsdSchemaToken::AttributeGroup, s4); + machine.addTransition(s1, XsdSchemaToken::AnyAttribute, s5); + machine.addTransition(s1, XsdSchemaToken::Assert, s6); + + machine.addTransition(s2, XsdSchemaToken::Group, s3); + machine.addTransition(s2, XsdSchemaToken::All, s3); + machine.addTransition(s2, XsdSchemaToken::Choice, s3); + machine.addTransition(s2, XsdSchemaToken::Sequence, s3); + machine.addTransition(s2, XsdSchemaToken::Attribute, s4); + machine.addTransition(s2, XsdSchemaToken::AttributeGroup, s4); + machine.addTransition(s2, XsdSchemaToken::AnyAttribute, s5); + machine.addTransition(s2, XsdSchemaToken::Assert, s6); + + machine.addTransition(s3, XsdSchemaToken::Attribute, s4); + machine.addTransition(s3, XsdSchemaToken::AttributeGroup, s4); + machine.addTransition(s3, XsdSchemaToken::AnyAttribute, s5); + machine.addTransition(s3, XsdSchemaToken::Assert, s6); + + machine.addTransition(s4, XsdSchemaToken::Attribute, s4); + machine.addTransition(s4, XsdSchemaToken::AttributeGroup, s4); + machine.addTransition(s4, XsdSchemaToken::AnyAttribute, s5); + machine.addTransition(s4, XsdSchemaToken::Assert, s6); + + machine.addTransition(s5, XsdSchemaToken::Assert, s6); + + machine.addTransition(s6, XsdSchemaToken::Assert, s6); + + m_stateMachines.insert(XsdTagScope::ComplexContentRestriction, machine); + m_stateMachines.insert(XsdTagScope::ComplexContentExtension, machine); + } + + { + XsdStateMachine machine(m_namePool); + + // setup state machine for (annotation?, ((attribute | attributeGroup)*, anyAttribute?)) : named attribute group + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s3 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Annotation, s1); + machine.addTransition(startState, XsdSchemaToken::Attribute, s2); + machine.addTransition(startState, XsdSchemaToken::AttributeGroup, s2); + machine.addTransition(startState, XsdSchemaToken::AnyAttribute, s3); + + machine.addTransition(s1, XsdSchemaToken::Attribute, s2); + machine.addTransition(s1, XsdSchemaToken::AttributeGroup, s2); + machine.addTransition(s1, XsdSchemaToken::AnyAttribute, s3); + + machine.addTransition(s2, XsdSchemaToken::Attribute, s2); + machine.addTransition(s2, XsdSchemaToken::AttributeGroup, s2); + machine.addTransition(s2, XsdSchemaToken::AnyAttribute, s3); + + m_stateMachines.insert(XsdTagScope::NamedAttributeGroup, machine); + } + + { + XsdStateMachine machine(m_namePool); + + // setup state machine for (annotation?, (all | choice | sequence)?) : group + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Annotation, s1); + machine.addTransition(startState, XsdSchemaToken::All, s2); + machine.addTransition(startState, XsdSchemaToken::Choice, s2); + machine.addTransition(startState, XsdSchemaToken::Sequence, s2); + + machine.addTransition(s1, XsdSchemaToken::All, s2); + machine.addTransition(s1, XsdSchemaToken::Choice, s2); + machine.addTransition(s1, XsdSchemaToken::Sequence, s2); + + m_stateMachines.insert(XsdTagScope::NamedGroup, machine); + m_stateMachines.insert(XsdTagScope::ReferredGroup, machine); + } + + { + XsdStateMachine machine(m_namePool); + + // setup state machine for (annotation?, (element | any)*) : all + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Annotation, s1); + machine.addTransition(startState, XsdSchemaToken::Element, s2); + machine.addTransition(startState, XsdSchemaToken::Any, s2); + + machine.addTransition(s1, XsdSchemaToken::Element, s2); + machine.addTransition(s1, XsdSchemaToken::Any, s2); + + machine.addTransition(s2, XsdSchemaToken::Element, s2); + machine.addTransition(s2, XsdSchemaToken::Any, s2); + + m_stateMachines.insert(XsdTagScope::All, machine); + m_stateMachines.insert(XsdTagScope::LocalAll, machine); + } + + { + XsdStateMachine machine(m_namePool); + + // setup state machine for (annotation?, (element | group | choice | sequence | any)*) : choice sequence + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Annotation, s1); + machine.addTransition(startState, XsdSchemaToken::Element, s2); + machine.addTransition(startState, XsdSchemaToken::Group, s2); + machine.addTransition(startState, XsdSchemaToken::Choice, s2); + machine.addTransition(startState, XsdSchemaToken::Sequence, s2); + machine.addTransition(startState, XsdSchemaToken::Any, s2); + + machine.addTransition(s1, XsdSchemaToken::Element, s2); + machine.addTransition(s1, XsdSchemaToken::Group, s2); + machine.addTransition(s1, XsdSchemaToken::Choice, s2); + machine.addTransition(s1, XsdSchemaToken::Sequence, s2); + machine.addTransition(s1, XsdSchemaToken::Any, s2); + + machine.addTransition(s2, XsdSchemaToken::Element, s2); + machine.addTransition(s2, XsdSchemaToken::Group, s2); + machine.addTransition(s2, XsdSchemaToken::Choice, s2); + machine.addTransition(s2, XsdSchemaToken::Sequence, s2); + machine.addTransition(s2, XsdSchemaToken::Any, s2); + + m_stateMachines.insert(XsdTagScope::Choice, machine); + m_stateMachines.insert(XsdTagScope::LocalChoice, machine); + m_stateMachines.insert(XsdTagScope::Sequence, machine); + m_stateMachines.insert(XsdTagScope::LocalSequence, machine); + } + + { + XsdStateMachine machine(m_namePool); + + // setup state machine for (annotation?) : any/selector/field/notation/include/import/referred attribute group/anyAttribute/all facets/assert + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Annotation, s1); + + m_stateMachines.insert(XsdTagScope::Any, machine); + m_stateMachines.insert(XsdTagScope::Selector, machine); + m_stateMachines.insert(XsdTagScope::Field, machine); + m_stateMachines.insert(XsdTagScope::Notation, machine); + m_stateMachines.insert(XsdTagScope::Include, machine); + m_stateMachines.insert(XsdTagScope::Import, machine); + m_stateMachines.insert(XsdTagScope::ReferredAttributeGroup, machine); + m_stateMachines.insert(XsdTagScope::AnyAttribute, machine); + m_stateMachines.insert(XsdTagScope::MinExclusiveFacet, machine); + m_stateMachines.insert(XsdTagScope::MinInclusiveFacet, machine); + m_stateMachines.insert(XsdTagScope::MaxExclusiveFacet, machine); + m_stateMachines.insert(XsdTagScope::MaxInclusiveFacet, machine); + m_stateMachines.insert(XsdTagScope::TotalDigitsFacet, machine); + m_stateMachines.insert(XsdTagScope::FractionDigitsFacet, machine); + m_stateMachines.insert(XsdTagScope::LengthFacet, machine); + m_stateMachines.insert(XsdTagScope::MinLengthFacet, machine); + m_stateMachines.insert(XsdTagScope::MaxLengthFacet, machine); + m_stateMachines.insert(XsdTagScope::EnumerationFacet, machine); + m_stateMachines.insert(XsdTagScope::WhiteSpaceFacet, machine); + m_stateMachines.insert(XsdTagScope::PatternFacet, machine); + m_stateMachines.insert(XsdTagScope::Assert, machine); + m_stateMachines.insert(XsdTagScope::Assertion, machine); + } + + { + XsdStateMachine machine(m_namePool); + + // setup state machine for (annotation?, (selector, field+)) : unique/key/keyref + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::InternalState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::InternalState); + const XsdStateMachine::StateId s3 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Annotation, s1); + machine.addTransition(startState, XsdSchemaToken::Selector, s2); + + machine.addTransition(s1, XsdSchemaToken::Selector, s2); + machine.addTransition(s2, XsdSchemaToken::Field, s3); + machine.addTransition(s3, XsdSchemaToken::Field, s3); + + m_stateMachines.insert(XsdTagScope::Unique, machine); + m_stateMachines.insert(XsdTagScope::Key, machine); + m_stateMachines.insert(XsdTagScope::KeyRef, machine); + } + + { + XsdStateMachine machine(m_namePool); + + // setup state machine for (annotation?, (simpleType | complexType)?) : alternative + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Annotation, s1); + machine.addTransition(startState, XsdSchemaToken::SimpleType, s2); + machine.addTransition(startState, XsdSchemaToken::ComplexType, s2); + + machine.addTransition(s1, XsdSchemaToken::SimpleType, s2); + machine.addTransition(s1, XsdSchemaToken::ComplexType, s2); + + m_stateMachines.insert(XsdTagScope::Alternative, machine); + } + + { + XsdStateMachine machine(m_namePool); + + // setup state machine for (appinfo | documentation)* : annotation + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Appinfo, s1); + machine.addTransition(startState, XsdSchemaToken::Documentation, s1); + + machine.addTransition(s1, XsdSchemaToken::Appinfo, s1); + machine.addTransition(s1, XsdSchemaToken::Documentation, s1); + + m_stateMachines.insert(XsdTagScope::Annotation, machine); + } + + { + XsdStateMachine machine(m_namePool); + + // setup state machine for (annotation?, (restriction | list | union)) : simpleType + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::InternalState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Annotation, s1); + machine.addTransition(startState, XsdSchemaToken::Restriction, s2); + machine.addTransition(startState, XsdSchemaToken::List, s2); + machine.addTransition(startState, XsdSchemaToken::Union, s2); + + machine.addTransition(s1, XsdSchemaToken::Restriction, s2); + machine.addTransition(s1, XsdSchemaToken::List, s2); + machine.addTransition(s1, XsdSchemaToken::Union, s2); + + m_stateMachines.insert(XsdTagScope::GlobalSimpleType, machine); + m_stateMachines.insert(XsdTagScope::LocalSimpleType, machine); + } + + { + XsdStateMachine machine(m_namePool); + + // setup state machine for (annotation?, (simpleType?, (minExclusive | minInclusive | maxExclusive | maxInclusive | totalDigits | fractionDigits | length | minLength | maxLength | enumeration | whiteSpace | pattern | assertion)*)) : simple type restriction + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s3 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Annotation, s1); + machine.addTransition(startState, XsdSchemaToken::SimpleType, s2); + machine.addTransition(startState, XsdSchemaToken::MinExclusive, s3); + machine.addTransition(startState, XsdSchemaToken::MinInclusive, s3); + machine.addTransition(startState, XsdSchemaToken::MaxExclusive, s3); + machine.addTransition(startState, XsdSchemaToken::MaxInclusive, s3); + machine.addTransition(startState, XsdSchemaToken::TotalDigits, s3); + machine.addTransition(startState, XsdSchemaToken::FractionDigits, s3); + machine.addTransition(startState, XsdSchemaToken::Length, s3); + machine.addTransition(startState, XsdSchemaToken::MinLength, s3); + machine.addTransition(startState, XsdSchemaToken::MaxLength, s3); + machine.addTransition(startState, XsdSchemaToken::Enumeration, s3); + machine.addTransition(startState, XsdSchemaToken::WhiteSpace, s3); + machine.addTransition(startState, XsdSchemaToken::Pattern, s3); + machine.addTransition(startState, XsdSchemaToken::Assertion, s3); + + machine.addTransition(s1, XsdSchemaToken::SimpleType, s2); + machine.addTransition(s1, XsdSchemaToken::MinExclusive, s3); + machine.addTransition(s1, XsdSchemaToken::MinInclusive, s3); + machine.addTransition(s1, XsdSchemaToken::MaxExclusive, s3); + machine.addTransition(s1, XsdSchemaToken::MaxInclusive, s3); + machine.addTransition(s1, XsdSchemaToken::TotalDigits, s3); + machine.addTransition(s1, XsdSchemaToken::FractionDigits, s3); + machine.addTransition(s1, XsdSchemaToken::Length, s3); + machine.addTransition(s1, XsdSchemaToken::MinLength, s3); + machine.addTransition(s1, XsdSchemaToken::MaxLength, s3); + machine.addTransition(s1, XsdSchemaToken::Enumeration, s3); + machine.addTransition(s1, XsdSchemaToken::WhiteSpace, s3); + machine.addTransition(s1, XsdSchemaToken::Pattern, s3); + machine.addTransition(s1, XsdSchemaToken::Assertion, s3); + + machine.addTransition(s2, XsdSchemaToken::MinExclusive, s3); + machine.addTransition(s2, XsdSchemaToken::MinInclusive, s3); + machine.addTransition(s2, XsdSchemaToken::MaxExclusive, s3); + machine.addTransition(s2, XsdSchemaToken::MaxInclusive, s3); + machine.addTransition(s2, XsdSchemaToken::TotalDigits, s3); + machine.addTransition(s2, XsdSchemaToken::FractionDigits, s3); + machine.addTransition(s2, XsdSchemaToken::Length, s3); + machine.addTransition(s2, XsdSchemaToken::MinLength, s3); + machine.addTransition(s2, XsdSchemaToken::MaxLength, s3); + machine.addTransition(s2, XsdSchemaToken::Enumeration, s3); + machine.addTransition(s2, XsdSchemaToken::WhiteSpace, s3); + machine.addTransition(s2, XsdSchemaToken::Pattern, s3); + machine.addTransition(s2, XsdSchemaToken::Assertion, s3); + + machine.addTransition(s3, XsdSchemaToken::MinExclusive, s3); + machine.addTransition(s3, XsdSchemaToken::MinInclusive, s3); + machine.addTransition(s3, XsdSchemaToken::MaxExclusive, s3); + machine.addTransition(s3, XsdSchemaToken::MaxInclusive, s3); + machine.addTransition(s3, XsdSchemaToken::TotalDigits, s3); + machine.addTransition(s3, XsdSchemaToken::FractionDigits, s3); + machine.addTransition(s3, XsdSchemaToken::Length, s3); + machine.addTransition(s3, XsdSchemaToken::MinLength, s3); + machine.addTransition(s3, XsdSchemaToken::MaxLength, s3); + machine.addTransition(s3, XsdSchemaToken::Enumeration, s3); + machine.addTransition(s3, XsdSchemaToken::WhiteSpace, s3); + machine.addTransition(s3, XsdSchemaToken::Pattern, s3); + machine.addTransition(s3, XsdSchemaToken::Assertion, s3); + + m_stateMachines.insert(XsdTagScope::SimpleRestriction, machine); + } + + { + XsdStateMachine machine(m_namePool); + + // setup state machine for (annotation?, simpleType?) : list + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Annotation, s1); + machine.addTransition(startState, XsdSchemaToken::SimpleType, s2); + + machine.addTransition(s1, XsdSchemaToken::SimpleType, s2); + + m_stateMachines.insert(XsdTagScope::List, machine); + } + + { + XsdStateMachine machine(m_namePool); + + // setup state machine for (annotation?, simpleType*) : union + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Annotation, s1); + machine.addTransition(startState, XsdSchemaToken::SimpleType, s2); + + machine.addTransition(s1, XsdSchemaToken::SimpleType, s2); + machine.addTransition(s2, XsdSchemaToken::SimpleType, s2); + + m_stateMachines.insert(XsdTagScope::Union, machine); + } + + { + XsdStateMachine machine(m_namePool); + + // setup state machine for ((include | import | redefine |i override | annotation)*, (defaultOpenContent, annotation*)?, (((simpleType | complexType | group | attributeGroup) | element | attribute | notation), annotation*)*) : schema + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s3 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s4 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s5 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Include, s1); + machine.addTransition(startState, XsdSchemaToken::Import, s1); + machine.addTransition(startState, XsdSchemaToken::Redefine, s1); + machine.addTransition(startState, XsdSchemaToken::Override, s1); + machine.addTransition(startState, XsdSchemaToken::Annotation, s1); + machine.addTransition(startState, XsdSchemaToken::DefaultOpenContent, s2); + machine.addTransition(startState, XsdSchemaToken::SimpleType, s4); + machine.addTransition(startState, XsdSchemaToken::ComplexType, s4); + machine.addTransition(startState, XsdSchemaToken::Group, s4); + machine.addTransition(startState, XsdSchemaToken::AttributeGroup, s4); + machine.addTransition(startState, XsdSchemaToken::Element, s4); + machine.addTransition(startState, XsdSchemaToken::Attribute, s4); + machine.addTransition(startState, XsdSchemaToken::Notation, s4); + + machine.addTransition(s1, XsdSchemaToken::Include, s1); + machine.addTransition(s1, XsdSchemaToken::Import, s1); + machine.addTransition(s1, XsdSchemaToken::Redefine, s1); + machine.addTransition(s1, XsdSchemaToken::Override, s1); + machine.addTransition(s1, XsdSchemaToken::Annotation, s1); + machine.addTransition(s1, XsdSchemaToken::DefaultOpenContent, s2); + machine.addTransition(s1, XsdSchemaToken::SimpleType, s4); + machine.addTransition(s1, XsdSchemaToken::ComplexType, s4); + machine.addTransition(s1, XsdSchemaToken::Group, s4); + machine.addTransition(s1, XsdSchemaToken::AttributeGroup, s4); + machine.addTransition(s1, XsdSchemaToken::Element, s4); + machine.addTransition(s1, XsdSchemaToken::Attribute, s4); + machine.addTransition(s1, XsdSchemaToken::Notation, s4); + + machine.addTransition(s2, XsdSchemaToken::Annotation, s3); + machine.addTransition(s2, XsdSchemaToken::SimpleType, s4); + machine.addTransition(s2, XsdSchemaToken::ComplexType, s4); + machine.addTransition(s2, XsdSchemaToken::Group, s4); + machine.addTransition(s2, XsdSchemaToken::AttributeGroup, s4); + machine.addTransition(s2, XsdSchemaToken::Element, s4); + machine.addTransition(s2, XsdSchemaToken::Attribute, s4); + machine.addTransition(s2, XsdSchemaToken::Notation, s4); + + machine.addTransition(s3, XsdSchemaToken::SimpleType, s4); + machine.addTransition(s3, XsdSchemaToken::ComplexType, s4); + machine.addTransition(s3, XsdSchemaToken::Group, s4); + machine.addTransition(s3, XsdSchemaToken::AttributeGroup, s4); + machine.addTransition(s3, XsdSchemaToken::Element, s4); + machine.addTransition(s3, XsdSchemaToken::Attribute, s4); + machine.addTransition(s3, XsdSchemaToken::Notation, s4); + + machine.addTransition(s4, XsdSchemaToken::SimpleType, s4); + machine.addTransition(s4, XsdSchemaToken::ComplexType, s4); + machine.addTransition(s4, XsdSchemaToken::Group, s4); + machine.addTransition(s4, XsdSchemaToken::AttributeGroup, s4); + machine.addTransition(s4, XsdSchemaToken::Element, s4); + machine.addTransition(s4, XsdSchemaToken::Attribute, s4); + machine.addTransition(s4, XsdSchemaToken::Notation, s4); + machine.addTransition(s4, XsdSchemaToken::Annotation, s5); + + machine.addTransition(s5, XsdSchemaToken::SimpleType, s4); + machine.addTransition(s5, XsdSchemaToken::ComplexType, s4); + machine.addTransition(s5, XsdSchemaToken::Group, s4); + machine.addTransition(s5, XsdSchemaToken::AttributeGroup, s4); + machine.addTransition(s5, XsdSchemaToken::Element, s4); + machine.addTransition(s5, XsdSchemaToken::Attribute, s4); + machine.addTransition(s5, XsdSchemaToken::Notation, s4); + machine.addTransition(s5, XsdSchemaToken::Annotation, s5); + + m_stateMachines.insert(XsdTagScope::Schema, machine); + } + + { + XsdStateMachine machine(m_namePool); + + // setup state machine for (annotation?, any) : defaultOpenContent + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::InternalState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Annotation, s1); + machine.addTransition(startState, XsdSchemaToken::Any, s2); + + machine.addTransition(s1, XsdSchemaToken::Any, s2); + + m_stateMachines.insert(XsdTagScope::DefaultOpenContent, machine); + } + + { + XsdStateMachine machine(m_namePool); + + // setup state machine for (annotation | (simpleType | complexType | group | attributeGroup))* : redefine + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Annotation, s1); + machine.addTransition(startState, XsdSchemaToken::SimpleType, s1); + machine.addTransition(startState, XsdSchemaToken::ComplexType, s1); + machine.addTransition(startState, XsdSchemaToken::Group, s1); + machine.addTransition(startState, XsdSchemaToken::AttributeGroup, s1); + + machine.addTransition(s1, XsdSchemaToken::Annotation, s1); + machine.addTransition(s1, XsdSchemaToken::SimpleType, s1); + machine.addTransition(s1, XsdSchemaToken::ComplexType, s1); + machine.addTransition(s1, XsdSchemaToken::Group, s1); + machine.addTransition(s1, XsdSchemaToken::AttributeGroup, s1); + + m_stateMachines.insert(XsdTagScope::Redefine, machine); + } + + { + XsdStateMachine machine(m_namePool); + + // setup state machine for (annotation | (simpleType | complexType | group | attributeGroup | element | attribute | notation))* : override + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Annotation, s1); + machine.addTransition(startState, XsdSchemaToken::SimpleType, s1); + machine.addTransition(startState, XsdSchemaToken::ComplexType, s1); + machine.addTransition(startState, XsdSchemaToken::Group, s1); + machine.addTransition(startState, XsdSchemaToken::AttributeGroup, s1); + machine.addTransition(startState, XsdSchemaToken::Element, s1); + machine.addTransition(startState, XsdSchemaToken::Attribute, s1); + machine.addTransition(startState, XsdSchemaToken::Notation, s1); + + machine.addTransition(s1, XsdSchemaToken::Annotation, s1); + machine.addTransition(s1, XsdSchemaToken::SimpleType, s1); + machine.addTransition(s1, XsdSchemaToken::ComplexType, s1); + machine.addTransition(s1, XsdSchemaToken::Group, s1); + machine.addTransition(s1, XsdSchemaToken::AttributeGroup, s1); + machine.addTransition(s1, XsdSchemaToken::Element, s1); + machine.addTransition(s1, XsdSchemaToken::Attribute, s1); + machine.addTransition(s1, XsdSchemaToken::Notation, s1); + + m_stateMachines.insert(XsdTagScope::Override, machine); + } +} + +void XsdSchemaParser::setupBuiltinTypeNames() +{ + m_builtinTypeNames.reserve(48); + + m_builtinTypeNames.insert(BuiltinTypes::xsAnyType->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsAnySimpleType->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsUntyped->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsAnyAtomicType->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsUntypedAtomic->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsDateTime->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsDate->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsTime->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsDuration->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsYearMonthDuration->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsDayTimeDuration->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsFloat->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsDouble->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsInteger->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsDecimal->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsNonPositiveInteger->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsNegativeInteger->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsLong->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsInt->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsShort->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsByte->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsNonNegativeInteger->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsUnsignedLong->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsUnsignedInt->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsUnsignedShort->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsUnsignedByte->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsPositiveInteger->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsGYearMonth->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsGYear->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsGMonthDay->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsGDay->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsGMonth->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsBoolean->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsBase64Binary->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsHexBinary->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsAnyURI->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsQName->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsString->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsNormalizedString->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsToken->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsLanguage->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsNMTOKEN->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsName->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsNCName->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsID->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsIDREF->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsENTITY->name(m_namePool)); + m_builtinTypeNames.insert(BuiltinTypes::xsNOTATION->name(m_namePool)); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdschemaparsercontext.cpp b/src/xmlpatterns/schema/qxsdschemaparsercontext.cpp new file mode 100644 index 0000000..896619e --- /dev/null +++ b/src/xmlpatterns/schema/qxsdschemaparsercontext.cpp @@ -0,0 +1,573 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qxsdschemaparsercontext_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +XsdSchemaParserContext::XsdSchemaParserContext(const NamePool::Ptr &namePool, const XsdSchemaContext::Ptr &context) + : m_namePool(namePool) + , m_schema(new XsdSchema(m_namePool)) + , m_checker(new XsdSchemaChecker(context, this)) + , m_resolver(new XsdSchemaResolver(context, this)) + , m_elementDescriptions(setupElementDescriptions()) +{ +} + +NamePool::Ptr XsdSchemaParserContext::namePool() const +{ + return m_namePool; +} + +XsdSchemaResolver::Ptr XsdSchemaParserContext::resolver() const +{ + return m_resolver; +} + +XsdSchemaChecker::Ptr XsdSchemaParserContext::checker() const +{ + return m_checker; +} + +XsdSchema::Ptr XsdSchemaParserContext::schema() const +{ + return m_schema; +} + +ElementDescription::Hash XsdSchemaParserContext::elementDescriptions() const +{ + return m_elementDescriptions; +} + +QXmlName XsdSchemaParserContext::createAnonymousName(const QString &targetNamespace) const +{ + m_anonymousNameCounter.ref(); + + const QString name = QString::fromLatin1("__AnonymousClass_%1").arg((int)m_anonymousNameCounter); + + return m_namePool->allocateQName(targetNamespace, name); +} + +ElementDescription::Hash XsdSchemaParserContext::setupElementDescriptions() +{ + enum + { + ReservedForElements = 60 + }; + + ElementDescription::Hash elementDescriptions; + elementDescriptions.reserve(ReservedForElements); + + { + ElementDescription &description = elementDescriptions[XsdTagScope::Schema]; + description.optionalAttributes.reserve(10); + //description.tagToken = XsdSchemaToken::Schema; + description.optionalAttributes.insert(XsdSchemaToken::AttributeFormDefault); + description.optionalAttributes.insert(XsdSchemaToken::BlockDefault); + description.optionalAttributes.insert(XsdSchemaToken::DefaultAttributes); + description.optionalAttributes.insert(XsdSchemaToken::XPathDefaultNamespace); + description.optionalAttributes.insert(XsdSchemaToken::ElementFormDefault); + description.optionalAttributes.insert(XsdSchemaToken::FinalDefault); + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.optionalAttributes.insert(XsdSchemaToken::TargetNamespace); + description.optionalAttributes.insert(XsdSchemaToken::Version); + description.optionalAttributes.insert(XsdSchemaToken::XmlLanguage); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::Include]; + //description.tagToken = XsdSchemaToken::Include; + description.requiredAttributes.insert(XsdSchemaToken::SchemaLocation); + description.optionalAttributes.insert(XsdSchemaToken::Id); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::Import]; + //description.tagToken = XsdSchemaToken::Import; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.optionalAttributes.insert(XsdSchemaToken::Namespace); + description.optionalAttributes.insert(XsdSchemaToken::SchemaLocation); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::Redefine]; + //description.tagToken = XsdSchemaToken::Redefine; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::SchemaLocation); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::Override]; + //description.tagToken = XsdSchemaToken::Override; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::SchemaLocation); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::Annotation]; + //description.tagToken = XsdSchemaToken::Annotation; + description.optionalAttributes.insert(XsdSchemaToken::Id); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::AppInfo]; + //description.tagToken = XsdSchemaToken::Appinfo; + description.optionalAttributes.insert(XsdSchemaToken::Source); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::Documentation]; + //description.tagToken = XsdSchemaToken::Documentation; + description.optionalAttributes.insert(XsdSchemaToken::Source); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::GlobalSimpleType]; + //description.tagToken = XsdSchemaToken::SimpleType; + description.optionalAttributes.insert(XsdSchemaToken::Final); + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Name); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::LocalSimpleType]; + //description.tagToken = XsdSchemaToken::SimpleType; + description.optionalAttributes.insert(XsdSchemaToken::Id); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::SimpleRestriction]; + //description.tagToken = XsdSchemaToken::Restriction; + description.optionalAttributes.insert(XsdSchemaToken::Base); + description.optionalAttributes.insert(XsdSchemaToken::Id); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::List]; + //description.tagToken = XsdSchemaToken::List; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.optionalAttributes.insert(XsdSchemaToken::ItemType); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::Union]; + //description.tagToken = XsdSchemaToken::Union; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.optionalAttributes.insert(XsdSchemaToken::MemberTypes); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::MinExclusiveFacet]; + //description.tagToken = XsdSchemaToken::MinExclusive; + description.optionalAttributes.insert(XsdSchemaToken::Fixed); + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Value); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::MinInclusiveFacet]; + //description.tagToken = XsdSchemaToken::MinInclusive; + description.optionalAttributes.insert(XsdSchemaToken::Fixed); + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Value); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::MaxExclusiveFacet]; + //description.tagToken = XsdSchemaToken::MaxExclusive; + description.optionalAttributes.insert(XsdSchemaToken::Fixed); + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Value); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::MaxInclusiveFacet]; + //description.tagToken = XsdSchemaToken::MaxInclusive; + description.optionalAttributes.insert(XsdSchemaToken::Fixed); + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Value); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::TotalDigitsFacet]; + //description.tagToken = XsdSchemaToken::TotalDigits; + description.optionalAttributes.insert(XsdSchemaToken::Fixed); + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Value); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::FractionDigitsFacet]; + //description.tagToken = XsdSchemaToken::FractionDigits; + description.optionalAttributes.insert(XsdSchemaToken::Fixed); + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Value); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::LengthFacet]; + //description.tagToken = XsdSchemaToken::Length; + description.optionalAttributes.insert(XsdSchemaToken::Fixed); + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Value); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::MinLengthFacet]; + //description.tagToken = XsdSchemaToken::MinLength; + description.optionalAttributes.insert(XsdSchemaToken::Fixed); + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Value); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::MaxLengthFacet]; + //description.tagToken = XsdSchemaToken::MaxLength; + description.optionalAttributes.insert(XsdSchemaToken::Fixed); + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Value); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::EnumerationFacet]; + //description.tagToken = XsdSchemaToken::Enumeration; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Value); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::WhiteSpaceFacet]; + //description.tagToken = XsdSchemaToken::WhiteSpace; + description.optionalAttributes.insert(XsdSchemaToken::Fixed); + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Value); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::PatternFacet]; + //description.tagToken = XsdSchemaToken::Pattern; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Value); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::GlobalComplexType]; + description.optionalAttributes.reserve(7); + //description.tagToken = XsdSchemaToken::ComplexType; + description.optionalAttributes.insert(XsdSchemaToken::Abstract); + description.optionalAttributes.insert(XsdSchemaToken::Block); + description.optionalAttributes.insert(XsdSchemaToken::DefaultAttributesApply); + description.optionalAttributes.insert(XsdSchemaToken::Final); + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.optionalAttributes.insert(XsdSchemaToken::Mixed); + description.requiredAttributes.insert(XsdSchemaToken::Name); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::LocalComplexType]; + //description.tagToken = XsdSchemaToken::ComplexType; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.optionalAttributes.insert(XsdSchemaToken::Mixed); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::SimpleContent]; + //description.tagToken = XsdSchemaToken::SimpleContent; + description.optionalAttributes.insert(XsdSchemaToken::Id); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::SimpleContentRestriction]; + //description.tagToken = XsdSchemaToken::Restriction; + description.requiredAttributes.insert(XsdSchemaToken::Base); + description.optionalAttributes.insert(XsdSchemaToken::Id); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::SimpleContentExtension]; + //description.tagToken = XsdSchemaToken::Extension; + description.requiredAttributes.insert(XsdSchemaToken::Base); + description.optionalAttributes.insert(XsdSchemaToken::Id); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::ComplexContent]; + //description.tagToken = XsdSchemaToken::ComplexContent; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.optionalAttributes.insert(XsdSchemaToken::Mixed); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::ComplexContentRestriction]; + //description.tagToken = XsdSchemaToken::Restriction; + description.requiredAttributes.insert(XsdSchemaToken::Base); + description.optionalAttributes.insert(XsdSchemaToken::Id); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::ComplexContentExtension]; + //description.tagToken = XsdSchemaToken::Extension; + description.requiredAttributes.insert(XsdSchemaToken::Base); + description.optionalAttributes.insert(XsdSchemaToken::Id); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::NamedGroup]; + //description.tagToken = XsdSchemaToken::Group; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Name); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::ReferredGroup]; + description.optionalAttributes.reserve(4); + //description.tagToken = XsdSchemaToken::Group; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.optionalAttributes.insert(XsdSchemaToken::MaxOccurs); + description.optionalAttributes.insert(XsdSchemaToken::MinOccurs); + description.requiredAttributes.insert(XsdSchemaToken::Ref); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::All]; + //description.tagToken = XsdSchemaToken::All; + description.optionalAttributes.insert(XsdSchemaToken::Id); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::LocalAll]; + //description.tagToken = XsdSchemaToken::All; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.optionalAttributes.insert(XsdSchemaToken::MaxOccurs); + description.optionalAttributes.insert(XsdSchemaToken::MinOccurs); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::Choice]; + //description.tagToken = XsdSchemaToken::Choice; + description.optionalAttributes.insert(XsdSchemaToken::Id); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::LocalChoice]; + //description.tagToken = XsdSchemaToken::Choice; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.optionalAttributes.insert(XsdSchemaToken::MaxOccurs); + description.optionalAttributes.insert(XsdSchemaToken::MinOccurs); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::Sequence]; + //description.tagToken = XsdSchemaToken::Sequence; + description.optionalAttributes.insert(XsdSchemaToken::Id); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::LocalSequence]; + //description.tagToken = XsdSchemaToken::Sequence; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.optionalAttributes.insert(XsdSchemaToken::MaxOccurs); + description.optionalAttributes.insert(XsdSchemaToken::MinOccurs); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::GlobalAttribute]; + description.optionalAttributes.reserve(5); + //description.tagToken = XsdSchemaToken::Attribute; + description.optionalAttributes.insert(XsdSchemaToken::Default); + description.optionalAttributes.insert(XsdSchemaToken::Fixed); + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Name); + description.optionalAttributes.insert(XsdSchemaToken::Type); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::LocalAttribute]; + description.optionalAttributes.reserve(8); + //description.tagToken = XsdSchemaToken::Attribute; + description.optionalAttributes.insert(XsdSchemaToken::Default); + description.optionalAttributes.insert(XsdSchemaToken::Fixed); + description.optionalAttributes.insert(XsdSchemaToken::Form); + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.optionalAttributes.insert(XsdSchemaToken::Name); + description.optionalAttributes.insert(XsdSchemaToken::Ref); + description.optionalAttributes.insert(XsdSchemaToken::Type); + description.optionalAttributes.insert(XsdSchemaToken::Use); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::NamedAttributeGroup]; + //description.tagToken = XsdSchemaToken::AttributeGroup; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Name); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::ReferredAttributeGroup]; + //description.tagToken = XsdSchemaToken::AttributeGroup; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Ref); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::LocalElement]; + description.optionalAttributes.reserve(11); + //description.tagToken = XsdSchemaToken::Element; + description.optionalAttributes.insert(XsdSchemaToken::Block); + description.optionalAttributes.insert(XsdSchemaToken::Default); + description.optionalAttributes.insert(XsdSchemaToken::Fixed); + description.optionalAttributes.insert(XsdSchemaToken::Form); + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.optionalAttributes.insert(XsdSchemaToken::MinOccurs); + description.optionalAttributes.insert(XsdSchemaToken::MaxOccurs); + description.optionalAttributes.insert(XsdSchemaToken::Name); + description.optionalAttributes.insert(XsdSchemaToken::Nillable); + description.optionalAttributes.insert(XsdSchemaToken::Ref); + description.optionalAttributes.insert(XsdSchemaToken::Type); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::GlobalElement]; + description.optionalAttributes.reserve(10); + //description.tagToken = XsdSchemaToken::Element; + description.optionalAttributes.insert(XsdSchemaToken::Abstract); + description.optionalAttributes.insert(XsdSchemaToken::Block); + description.optionalAttributes.insert(XsdSchemaToken::Default); + description.optionalAttributes.insert(XsdSchemaToken::Final); + description.optionalAttributes.insert(XsdSchemaToken::Fixed); + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Name); + description.optionalAttributes.insert(XsdSchemaToken::Nillable); + description.optionalAttributes.insert(XsdSchemaToken::SubstitutionGroup); + description.optionalAttributes.insert(XsdSchemaToken::Type); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::Unique]; + //description.tagToken = XsdSchemaToken::Unique; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Name); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::Key]; + //description.tagToken = XsdSchemaToken::Key; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Name); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::KeyRef]; + //description.tagToken = XsdSchemaToken::Keyref; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Name); + description.requiredAttributes.insert(XsdSchemaToken::Refer); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::Selector]; + //description.tagToken = XsdSchemaToken::Selector; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Xpath); + description.optionalAttributes.insert(XsdSchemaToken::XPathDefaultNamespace); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::Field]; + //description.tagToken = XsdSchemaToken::Field; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Xpath); + description.optionalAttributes.insert(XsdSchemaToken::XPathDefaultNamespace); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::Notation]; + description.optionalAttributes.reserve(4); + //description.tagToken = XsdSchemaToken::Notation; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Name); + description.optionalAttributes.insert(XsdSchemaToken::Public); + description.optionalAttributes.insert(XsdSchemaToken::System); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::Any]; + description.optionalAttributes.reserve(7); + //description.tagToken = XsdSchemaToken::Any; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.optionalAttributes.insert(XsdSchemaToken::MaxOccurs); + description.optionalAttributes.insert(XsdSchemaToken::MinOccurs); + description.optionalAttributes.insert(XsdSchemaToken::Namespace); + description.optionalAttributes.insert(XsdSchemaToken::NotNamespace); + description.optionalAttributes.insert(XsdSchemaToken::NotQName); + description.optionalAttributes.insert(XsdSchemaToken::ProcessContents); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::AnyAttribute]; + description.optionalAttributes.reserve(5); + //description.tagToken = XsdSchemaToken::AnyAttribute; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.optionalAttributes.insert(XsdSchemaToken::Namespace); + description.optionalAttributes.insert(XsdSchemaToken::NotNamespace); + description.optionalAttributes.insert(XsdSchemaToken::NotQName); + description.optionalAttributes.insert(XsdSchemaToken::ProcessContents); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::Alternative]; + //description.tagToken = XsdSchemaToken::Alternative; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.optionalAttributes.insert(XsdSchemaToken::Test); + description.optionalAttributes.insert(XsdSchemaToken::Type); + description.optionalAttributes.insert(XsdSchemaToken::XPathDefaultNamespace); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::OpenContent]; + //description.tagToken = XsdSchemaToken::OpenContent; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.optionalAttributes.insert(XsdSchemaToken::Mode); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::DefaultOpenContent]; + //description.tagToken = XsdSchemaToken::DefaultOpenContent; + description.optionalAttributes.insert(XsdSchemaToken::AppliesToEmpty); + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.optionalAttributes.insert(XsdSchemaToken::Mode); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::Assert]; + //description.tagToken = XsdSchemaToken::Assert; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Test); + description.optionalAttributes.insert(XsdSchemaToken::XPathDefaultNamespace); + } + + { + ElementDescription &description = elementDescriptions[XsdTagScope::Assertion]; + //description.tagToken = XsdSchemaToken::Assertion; + description.optionalAttributes.insert(XsdSchemaToken::Id); + description.requiredAttributes.insert(XsdSchemaToken::Test); + description.optionalAttributes.insert(XsdSchemaToken::XPathDefaultNamespace); + } + + Q_ASSERT_X(elementDescriptions.count() == ReservedForElements, Q_FUNC_INFO, + qPrintable(QString::fromLatin1("Expected is %1, actual is %2.").arg(ReservedForElements).arg(elementDescriptions.count()))); + + return elementDescriptions; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdschemaparsercontext_p.h b/src/xmlpatterns/schema/qxsdschemaparsercontext_p.h new file mode 100644 index 0000000..616aff3 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdschemaparsercontext_p.h @@ -0,0 +1,201 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdSchemaParserContext_H +#define Patternist_XsdSchemaParserContext_H + +#include "qmaintainingreader_p.h" // for definition of ElementDescription +#include "qxsdschematoken_p.h" +#include "qxsdschema_p.h" +#include "qxsdschemachecker_p.h" +#include "qxsdschemacontext_p.h" +#include "qxsdschemaresolver_p.h" + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short A namespace class that contains identifiers for the different + * scopes a tag from the xml schema spec can appear in. + */ + class XsdTagScope + { + public: + enum Type + { + Schema, + Include, + Import, + Redefine, + Annotation, + AppInfo, + Documentation, + GlobalSimpleType, + LocalSimpleType, + SimpleRestriction, + List, + Union, + MinExclusiveFacet, + MinInclusiveFacet, + MaxExclusiveFacet, + MaxInclusiveFacet, + TotalDigitsFacet, + FractionDigitsFacet, + LengthFacet, + MinLengthFacet, + MaxLengthFacet, + EnumerationFacet, + WhiteSpaceFacet, + PatternFacet, + GlobalComplexType, + LocalComplexType, + SimpleContent, + SimpleContentRestriction, + SimpleContentExtension, + ComplexContent, + ComplexContentRestriction, + ComplexContentExtension, + NamedGroup, + ReferredGroup, + All, + LocalAll, + Choice, + LocalChoice, + Sequence, + LocalSequence, + GlobalAttribute, + LocalAttribute, + NamedAttributeGroup, + ReferredAttributeGroup, + GlobalElement, + LocalElement, + Unique, + Key, + KeyRef, + Selector, + Field, + Notation, + Any, + AnyAttribute, + Alternative, + Assert, + Assertion, + OpenContent, + DefaultOpenContent, + Override + }; + }; + + /** + * A hash that keeps the mapping between the single components that can appear + * in a schema document (e.g. elements, attributes, type definitions) and their + * source locations inside the document. + */ + typedef QHash ComponentLocationHash; + + /** + * @short A context for schema parsing. + * + * This class provides a context for all components that are + * nedded for parsing and compiling the XML schema. + * + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdSchemaParserContext : public QSharedData + { + public: + /** + * A smart pointer wrapping XsdSchemaParserContext instances. + */ + typedef QExplicitlySharedDataPointer Ptr; + + /** + * Creates a new schema parser context object. + * + * @param namePool The name pool where all names of the schema will be stored in. + * @param context The schema context to use for error reporting etc. + */ + XsdSchemaParserContext(const NamePool::Ptr &namePool, const XsdSchemaContext::Ptr &context); + + /** + * Returns the name pool of the schema parser context. + */ + NamePool::Ptr namePool() const; + + /** + * Returns the schema resolver of the schema context. + */ + XsdSchemaResolver::Ptr resolver() const; + + /** + * Returns the schema resolver of the schema context. + */ + XsdSchemaChecker::Ptr checker() const; + + /** + * Returns the schema object of the schema context. + */ + XsdSchema::Ptr schema() const; + + /** + * Returns the element descriptions for the schema parser. + * + * The element descriptions are a fast lookup table for + * verifying whether certain attributes are allowed for + * a given element type. + */ + ElementDescription::Hash elementDescriptions() const; + + /** + * Returns an unique name that is used by the schema parser + * for anonymous types. + * + * @param targetNamespace The namespace of the name. + */ + QXmlName createAnonymousName(const QString &targetNamespace) const; + + private: + /** + * Fills the element description hash with the required and prohibited + * attributes. + */ + static ElementDescription::Hash setupElementDescriptions(); + + NamePool::Ptr m_namePool; + XsdSchema::Ptr m_schema; + XsdSchemaChecker::Ptr m_checker; + XsdSchemaResolver::Ptr m_resolver; + const ElementDescription::Hash m_elementDescriptions; + mutable QAtomicInt m_anonymousNameCounter; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsdschemaresolver.cpp b/src/xmlpatterns/schema/qxsdschemaresolver.cpp new file mode 100644 index 0000000..4c6910f --- /dev/null +++ b/src/xmlpatterns/schema/qxsdschemaresolver.cpp @@ -0,0 +1,1706 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qxsdschemaresolver_p.h" + +#include "qderivedinteger_p.h" +#include "qderivedstring_p.h" +#include "qqnamevalue_p.h" +#include "qxsdattributereference_p.h" +#include "qxsdparticlechecker_p.h" +#include "qxsdreference_p.h" +#include "qxsdschemacontext_p.h" +#include "qxsdschemahelper_p.h" +#include "qxsdschemaparsercontext_p.h" +#include "qxsdschematypesfactory_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +XsdSchemaResolver::XsdSchemaResolver(const QExplicitlySharedDataPointer &context, const XsdSchemaParserContext *parserContext) + : m_context(context) + , m_checker(parserContext->checker()) + , m_namePool(parserContext->namePool()) + , m_schema(parserContext->schema()) +{ + m_keyReferences.reserve(20); + m_simpleRestrictionBases.reserve(20); + m_simpleListTypes.reserve(20); + m_simpleUnionTypes.reserve(20); + m_elementTypes.reserve(20); + m_complexBaseTypes.reserve(20); + m_attributeTypes.reserve(20); + m_alternativeTypes.reserve(20); + m_alternativeTypeElements.reserve(20); + m_substitutionGroupAffiliations.reserve(20); + + m_predefinedSchemaTypes = m_context->schemaTypeFactory()->types().values(); +} + +XsdSchemaResolver::~XsdSchemaResolver() +{ +} + +void XsdSchemaResolver::resolve() +{ + m_checker->addComponentLocationHash(m_componentLocationHash); + + // resolve the base types for all types + resolveSimpleRestrictionBaseTypes(); + resolveComplexBaseTypes(); + + // do the basic checks which depend on having a base type available + m_checker->basicCheck(); + + // resolve further types that only map a type name to a type object + resolveSimpleListType(); + resolveSimpleUnionTypes(); + resolveElementTypes(); + resolveAttributeTypes(); + resolveAlternativeTypes(); + + // resolve objects that do not need information about inheritance + resolveKeyReferences(); + resolveSubstitutionGroupAffiliations(); + + // resolve objects that do need information about inheritance + resolveSimpleRestrictions(); + resolveSimpleContentComplexTypes(); + + // resolve objects which replace place holders + resolveTermReferences(); + resolveAttributeTermReferences(); + + // resolve additional objects that do need information about inheritance + resolveAttributeInheritance(); + resolveComplexContentComplexTypes(); + resolveSubstitutionGroups(); + + resolveEnumerationFacetValues(); + + checkRedefinedGroups(); + checkRedefinedAttributeGroups(); + + // check the constraining facets before we resolve them + m_checker->checkConstrainingFacets(); + + // add it again, as we may have added new components in the meantime + m_checker->addComponentLocationHash(m_componentLocationHash); + + m_checker->check(); +} + +void XsdSchemaResolver::addKeyReference(const XsdElement::Ptr &element, const XsdIdentityConstraint::Ptr &keyRef, const QXmlName &reference, const QSourceLocation &location) +{ + KeyReference item; + item.element = element; + item.keyRef = keyRef; + item.reference = reference; + item.location = location; + + m_keyReferences.append(item); +} + +void XsdSchemaResolver::addSimpleRestrictionBase(const XsdSimpleType::Ptr &simpleType, const QXmlName &baseName, const QSourceLocation &location) +{ + SimpleRestrictionBase item; + item.simpleType = simpleType; + item.baseName = baseName; + item.location = location; + + m_simpleRestrictionBases.append(item); +} + +void XsdSchemaResolver::removeSimpleRestrictionBase(const XsdSimpleType::Ptr &type) +{ + for (int i = 0; i < m_simpleRestrictionBases.count(); ++i) { + if (m_simpleRestrictionBases.at(i).simpleType == type) { + m_simpleRestrictionBases.remove(i); + break; + } + } +} + +void XsdSchemaResolver::addSimpleListType(const XsdSimpleType::Ptr &simpleType, const QXmlName &typeName, const QSourceLocation &location) +{ + SimpleListType item; + item.simpleType = simpleType; + item.typeName = typeName; + item.location = location; + + m_simpleListTypes.append(item); +} + +void XsdSchemaResolver::addSimpleUnionTypes(const XsdSimpleType::Ptr &simpleType, const QList &typeNames, const QSourceLocation &location) +{ + SimpleUnionType item; + item.simpleType = simpleType; + item.typeNames = typeNames; + item.location = location; + + m_simpleUnionTypes.append(item); +} + +void XsdSchemaResolver::addElementType(const XsdElement::Ptr &element, const QXmlName &typeName, const QSourceLocation &location) +{ + ElementType item; + item.element = element; + item.typeName = typeName; + item.location = location; + + m_elementTypes.append(item); +} + +void XsdSchemaResolver::addComplexBaseType(const XsdComplexType::Ptr &complexType, const QXmlName &baseName, const QSourceLocation &location, const XsdFacet::Hash &facets) +{ + ComplexBaseType item; + item.complexType = complexType; + item.baseName = baseName; + item.location = location; + item.facets = facets; + + m_complexBaseTypes.append(item); +} + +void XsdSchemaResolver::removeComplexBaseType(const XsdComplexType::Ptr &type) +{ + for (int i = 0; i < m_complexBaseTypes.count(); ++i) { + if (m_complexBaseTypes.at(i).complexType == type) { + m_complexBaseTypes.remove(i); + break; + } + } +} + +void XsdSchemaResolver::addComplexContentType(const XsdComplexType::Ptr &complexType, const XsdParticle::Ptr &content, bool mixed) +{ + ComplexContentType item; + item.complexType = complexType; + item.explicitContent = content; + item.effectiveMixed = mixed; + m_complexContentTypes.append(item); +} + +void XsdSchemaResolver::addAttributeType(const XsdAttribute::Ptr &attribute, const QXmlName &typeName, const QSourceLocation &location) +{ + AttributeType item; + item.attribute = attribute; + item.typeName = typeName; + item.location = location; + + m_attributeTypes.append(item); +} + +void XsdSchemaResolver::addAlternativeType(const XsdAlternative::Ptr &alternative, const QXmlName &typeName, const QSourceLocation &location) +{ + AlternativeType item; + item.alternative = alternative; + item.typeName = typeName; + item.location = location; + + m_alternativeTypes.append(item); +} + +void XsdSchemaResolver::addAlternativeType(const XsdAlternative::Ptr &alternative, const XsdElement::Ptr &element) +{ + AlternativeTypeElement item; + item.alternative = alternative; + item.element = element; + + m_alternativeTypeElements.append(item); +} + +void XsdSchemaResolver::addSubstitutionGroupAffiliation(const XsdElement::Ptr &element, const QList &elementNames, const QSourceLocation &location) +{ + SubstitutionGroupAffiliation item; + item.element = element; + item.elementNames = elementNames; + item.location = location; + + m_substitutionGroupAffiliations.append(item); +} + +void XsdSchemaResolver::addSubstitutionGroupType(const XsdElement::Ptr &element) +{ + m_substitutionGroupTypes.append(element); +} + +void XsdSchemaResolver::addComponentLocationHash(const ComponentLocationHash &hash) +{ + m_componentLocationHash.unite(hash); +} + +void XsdSchemaResolver::addEnumerationFacetValue(const AtomicValue::Ptr &facetValue, const NamespaceSupport &namespaceSupport) +{ + m_enumerationFacetValues.insert(facetValue, namespaceSupport); +} + +void XsdSchemaResolver::addRedefinedGroups(const XsdModelGroup::Ptr &redefinedGroup, const XsdModelGroup::Ptr &group) +{ + RedefinedGroups item; + item.redefinedGroup = redefinedGroup; + item.group = group; + + m_redefinedGroups.append(item); +} + +void XsdSchemaResolver::addRedefinedAttributeGroups(const XsdAttributeGroup::Ptr &redefinedGroup, const XsdAttributeGroup::Ptr &group) +{ + RedefinedAttributeGroups item; + item.redefinedGroup = redefinedGroup; + item.group = group; + + m_redefinedAttributeGroups.append(item); +} + +void XsdSchemaResolver::addAllGroupCheck(const XsdReference::Ptr &reference) +{ + m_allGroups.insert(reference); +} + +void XsdSchemaResolver::copyDataTo(const XsdSchemaResolver::Ptr &other) const +{ + other->m_keyReferences << m_keyReferences; + other->m_simpleRestrictionBases << m_simpleRestrictionBases; + other->m_simpleListTypes << m_simpleListTypes; + other->m_simpleUnionTypes << m_simpleUnionTypes; + other->m_elementTypes << m_elementTypes; + other->m_complexBaseTypes << m_complexBaseTypes; + other->m_complexContentTypes << m_complexContentTypes; + other->m_attributeTypes << m_attributeTypes; + other->m_alternativeTypes << m_alternativeTypes; + other->m_alternativeTypeElements << m_alternativeTypeElements; + other->m_substitutionGroupAffiliations << m_substitutionGroupAffiliations; + other->m_substitutionGroupTypes << m_substitutionGroupTypes; +} + +QXmlName XsdSchemaResolver::baseTypeNameOfType(const SchemaType::Ptr &type) const +{ + for (int i = 0; i < m_simpleRestrictionBases.count(); ++i) { + if (m_simpleRestrictionBases.at(i).simpleType == type) + return m_simpleRestrictionBases.at(i).baseName; + } + + for (int i = 0; i < m_complexBaseTypes.count(); ++i) { + if (m_complexBaseTypes.at(i).complexType == type) + return m_complexBaseTypes.at(i).baseName; + } + + return QXmlName(); +} + +QXmlName XsdSchemaResolver::typeNameOfAttribute(const XsdAttribute::Ptr &attribute) const +{ + for (int i = 0; i < m_attributeTypes.count(); ++i) { + if (m_attributeTypes.at(i).attribute == attribute) + return m_attributeTypes.at(i).typeName; + } + + return QXmlName(); +} + +void XsdSchemaResolver::setDefaultOpenContent(const XsdComplexType::OpenContent::Ptr &openContent, bool appliesToEmpty) +{ + m_defaultOpenContent = openContent; + m_defaultOpenContentAppliesToEmpty = appliesToEmpty; +} + +void XsdSchemaResolver::resolveKeyReferences() +{ + for (int i = 0; i < m_keyReferences.count(); ++i) { + const KeyReference ref = m_keyReferences.at(i); + + const XsdIdentityConstraint::Ptr constraint = m_schema->identityConstraint(ref.reference); + if (!constraint) { + m_context->error(QtXmlPatterns::tr("%1 references unknown %2 or %3 element %4") + .arg(formatKeyword(ref.keyRef->displayName(m_namePool))) + .arg(formatElement("key")) + .arg(formatElement("unique")) + .arg(formatKeyword(m_namePool, ref.reference)), + XsdSchemaContext::XSDError, ref.location); + return; + } + + if (constraint->category() != XsdIdentityConstraint::Key && constraint->category() != XsdIdentityConstraint::Unique) { // only key and unique can be referenced + m_context->error(QtXmlPatterns::tr("%1 references identity constraint %2 that is no %3 or %4 element") + .arg(formatKeyword(ref.keyRef->displayName(m_namePool))) + .arg(formatKeyword(m_namePool, ref.reference)) + .arg(formatElement("key")) + .arg(formatElement("unique")), + XsdSchemaContext::XSDError, ref.location); + return; + } + + if (constraint->fields().count() != ref.keyRef->fields().count()) { + m_context->error(QtXmlPatterns::tr("%1 has a different number of fields from the identity constraint %2 that it references") + .arg(formatKeyword(ref.keyRef->displayName(m_namePool))) + .arg(formatKeyword(m_namePool, ref.reference)), + XsdSchemaContext::XSDError, ref.location); + return; + } + + ref.keyRef->setReferencedKey(constraint); + } +} + +void XsdSchemaResolver::resolveSimpleRestrictionBaseTypes() +{ + // iterate over all simple types that are derived by restriction + for (int i = 0; i < m_simpleRestrictionBases.count(); ++i) { + const SimpleRestrictionBase item = m_simpleRestrictionBases.at(i); + + // find the base type + SchemaType::Ptr type = m_schema->type(item.baseName); + if (!type) { + // maybe it's a basic type... + type = m_context->schemaTypeFactory()->createSchemaType(item.baseName); + if (!type) { + m_context->error(QtXmlPatterns::tr("base type %1 of %2 element cannot be resolved") + .arg(formatType(m_namePool, item.baseName)) + .arg(formatElement("restriction")), + XsdSchemaContext::XSDError, item.location); + return; + } + } + + item.simpleType->setWxsSuperType(type); + } +} + +void XsdSchemaResolver::resolveSimpleRestrictions() +{ + XsdSimpleType::List simpleTypes; + + // first collect the global simple types + const SchemaType::List types = m_schema->types(); + for (int i = 0; i < types.count(); ++i) { + if (types.at(i)->isSimpleType() && (types.at(i)->derivationMethod() == SchemaType::DerivationRestriction)) + simpleTypes.append(types.at(i)); + } + + // then collect all anonymous simple types + const SchemaType::List anonymousTypes = m_schema->anonymousTypes(); + for (int i = 0; i < anonymousTypes.count(); ++i) { + if (anonymousTypes.at(i)->isSimpleType() && (anonymousTypes.at(i)->derivationMethod() == SchemaType::DerivationRestriction)) + simpleTypes.append(anonymousTypes.at(i)); + } + + QSet visitedTypes; + for (int i = 0; i < simpleTypes.count(); ++i) { + resolveSimpleRestrictions(simpleTypes.at(i), visitedTypes); + } +} + +void XsdSchemaResolver::resolveSimpleRestrictions(const XsdSimpleType::Ptr &simpleType, QSet &visitedTypes) +{ + if (visitedTypes.contains(simpleType)) + return; + else + visitedTypes.insert(simpleType); + + if (simpleType->derivationMethod() != XsdSimpleType::DerivationRestriction) + return; + + // as xs:NMTOKENS, xs:ENTITIES and xs:IDREFS are provided by our XsdSchemaTypesFactory, they are + // setup correctly already and shouldn't be handled here + if (m_predefinedSchemaTypes.contains(simpleType)) + return; + + const SchemaType::Ptr baseType = simpleType->wxsSuperType(); + Q_ASSERT(baseType); + + if (baseType->isDefinedBySchema()) + resolveSimpleRestrictions(XsdSimpleType::Ptr(baseType), visitedTypes); + + simpleType->setCategory(baseType->category()); + + if (simpleType->category() == XsdSimpleType::SimpleTypeAtomic) { + QSet visitedPrimitiveTypes; + const AnySimpleType::Ptr primitiveType = findPrimitiveType(baseType, visitedPrimitiveTypes); + simpleType->setPrimitiveType(primitiveType); + } else if (simpleType->category() == XsdSimpleType::SimpleTypeList) { + const XsdSimpleType::Ptr simpleBaseType = baseType; + simpleType->setItemType(simpleBaseType->itemType()); + } else if (simpleType->category() == XsdSimpleType::SimpleTypeUnion) { + const XsdSimpleType::Ptr simpleBaseType = baseType; + simpleType->setMemberTypes(simpleBaseType->memberTypes()); + } +} + +void XsdSchemaResolver::resolveSimpleListType() +{ + // iterate over all simple types where the item type shall be resolved + for (int i = 0; i < m_simpleListTypes.count(); ++i) { + const SimpleListType item = m_simpleListTypes.at(i); + + // try to resolve the name + SchemaType::Ptr type = m_schema->type(item.typeName); + if (!type) { + // maybe it's a basic type... + type = m_context->schemaTypeFactory()->createSchemaType(item.typeName); + if (!type) { + m_context->error(QtXmlPatterns::tr("item type %1 of %2 element cannot be resolved") + .arg(formatType(m_namePool, item.typeName)) + .arg(formatElement("list")), + XsdSchemaContext::XSDError, item.location); + return; + } + } + + item.simpleType->setItemType(type); + } +} + +void XsdSchemaResolver::resolveSimpleUnionTypes() +{ + // iterate over all simple types where the union member types shall be resolved + for (int i = 0; i < m_simpleUnionTypes.count(); ++i) { + const SimpleUnionType item = m_simpleUnionTypes.at(i); + + AnySimpleType::List memberTypes; + + // iterate over all union member type names + const QList typeNames = item.typeNames; + for (int j = 0; j < typeNames.count(); ++j) { + const QXmlName typeName = typeNames.at(j); + + // try to resolve the name + SchemaType::Ptr type = m_schema->type(typeName); + if (!type) { + // maybe it's a basic type... + type = m_context->schemaTypeFactory()->createSchemaType(typeName); + if (!type) { + m_context->error(QtXmlPatterns::tr("member type %1 of %2 element cannot be resolved") + .arg(formatType(m_namePool, typeName)) + .arg(formatElement("union")), + XsdSchemaContext::XSDError, item.location); + return; + } + } + + memberTypes.append(type); + } + + // append the types that have been defined as children + memberTypes << item.simpleType->memberTypes(); + + item.simpleType->setMemberTypes(memberTypes); + } +} + +void XsdSchemaResolver::resolveElementTypes() +{ + for (int i = 0; i < m_elementTypes.count(); ++i) { + const ElementType item = m_elementTypes.at(i); + + SchemaType::Ptr type = m_schema->type(item.typeName); + if (!type) { + // maybe it's a basic type... + type = m_context->schemaTypeFactory()->createSchemaType(item.typeName); + if (!type) { + m_context->error(QtXmlPatterns::tr("type %1 of %2 element cannot be resolved") + .arg(formatType(m_namePool, item.typeName)) + .arg(formatElement("element")), + XsdSchemaContext::XSDError, item.location); + return; + } + } + + item.element->setType(type); + } +} + +void XsdSchemaResolver::resolveComplexBaseTypes() +{ + for (int i = 0; i < m_complexBaseTypes.count(); ++i) { + const ComplexBaseType item = m_complexBaseTypes.at(i); + + SchemaType::Ptr type = m_schema->type(item.baseName); + if (!type) { + // maybe it's a basic type... + type = m_context->schemaTypeFactory()->createSchemaType(item.baseName); + if (!type) { + m_context->error(QtXmlPatterns::tr("base type %1 of complex type cannot be resolved").arg(formatType(m_namePool, item.baseName)), XsdSchemaContext::XSDError, item.location); + return; + } + } + + if (item.complexType->contentType()->variety() == XsdComplexType::ContentType::Simple) { + if (type->isComplexType() && type->isDefinedBySchema()) { + const XsdComplexType::Ptr baseType = type; + if (baseType->contentType()->variety() != XsdComplexType::ContentType::Simple) { + m_context->error(QtXmlPatterns::tr("%1 cannot have complex base type that has a %2") + .arg(formatElement("simpleContent")) + .arg(formatElement("complexContent")), + XsdSchemaContext::XSDError, item.location); + return; + } + } + } + + item.complexType->setWxsSuperType(type); + } +} + +void XsdSchemaResolver::resolveSimpleContentComplexTypes() +{ + XsdComplexType::List complexTypes; + + // first collect the global complex types + const SchemaType::List types = m_schema->types(); + for (int i = 0; i < types.count(); ++i) { + if (types.at(i)->isComplexType() && types.at(i)->isDefinedBySchema()) + complexTypes.append(types.at(i)); + } + + // then collect all anonymous simple types + const SchemaType::List anonymousTypes = m_schema->anonymousTypes(); + for (int i = 0; i < anonymousTypes.count(); ++i) { + if (anonymousTypes.at(i)->isComplexType() && anonymousTypes.at(i)->isDefinedBySchema()) + complexTypes.append(anonymousTypes.at(i)); + } + + QSet visitedTypes; + for (int i = 0; i < complexTypes.count(); ++i) { + if (XsdComplexType::Ptr(complexTypes.at(i))->contentType()->variety() == XsdComplexType::ContentType::Simple) + resolveSimpleContentComplexTypes(complexTypes.at(i), visitedTypes); + } +} + +void XsdSchemaResolver::resolveSimpleContentComplexTypes(const XsdComplexType::Ptr &complexType, QSet &visitedTypes) +{ + if (visitedTypes.contains(complexType)) + return; + else + visitedTypes.insert(complexType); + + const SchemaType::Ptr baseType = complexType->wxsSuperType(); + + // at this point simple types have been resolved already, so we care about + // complex types here only + + // http://www.w3.org/TR/xmlschema11-1/#dcl.ctd.ctsc + // 1 + if (baseType->isComplexType() && baseType->isDefinedBySchema()) { + const XsdComplexType::Ptr complexBaseType = baseType; + + resolveSimpleContentComplexTypes(complexBaseType, visitedTypes); + + if (complexBaseType->contentType()->variety() == XsdComplexType::ContentType::Simple) { + if (complexType->derivationMethod() == XsdComplexType::DerivationRestriction) { + if (complexType->contentType()->simpleType()) { + // 1.1 contains the content of the already + } else { + // 1.2 + const XsdSimpleType::Ptr anonType(new XsdSimpleType()); + anonType->setCategory(complexBaseType->contentType()->simpleType()->category()); + anonType->setDerivationMethod(XsdSimpleType::DerivationRestriction); + anonType->setWxsSuperType(complexBaseType->contentType()->simpleType()); + anonType->setFacets(complexTypeFacets(complexType)); + + QSet visitedPrimitiveTypes; + const AnySimpleType::Ptr primitiveType = findPrimitiveType(anonType->wxsSuperType(), visitedPrimitiveTypes); + anonType->setPrimitiveType(primitiveType); + + complexType->contentType()->setSimpleType(anonType); + + m_schema->addAnonymousType(anonType); + m_componentLocationHash.insert(anonType, m_componentLocationHash.value(complexType)); + } + } else if (complexBaseType->derivationMethod() == XsdComplexType::DerivationExtension) { // 3 + complexType->contentType()->setSimpleType(complexBaseType->contentType()->simpleType()); + } + } else if (complexBaseType->contentType()->variety() == XsdComplexType::ContentType::Mixed && + complexType->derivationMethod() == XsdComplexType::DerivationRestriction && + XsdSchemaHelper::isParticleEmptiable(complexBaseType->contentType()->particle())) { // 2 + // simple type was already set in parser + + const XsdSimpleType::Ptr anonType(new XsdSimpleType()); + anonType->setCategory(complexType->contentType()->simpleType()->category()); + anonType->setDerivationMethod(XsdSimpleType::DerivationRestriction); + anonType->setWxsSuperType(complexType->contentType()->simpleType()); + anonType->setFacets(complexTypeFacets(complexType)); + + QSet visitedPrimitiveTypes; + const AnySimpleType::Ptr primitiveType = findPrimitiveType(anonType->wxsSuperType(), visitedPrimitiveTypes); + anonType->setPrimitiveType(primitiveType); + + complexType->contentType()->setSimpleType(anonType); + + m_schema->addAnonymousType(anonType); + m_componentLocationHash.insert(anonType, m_componentLocationHash.value(complexType)); + } else { + complexType->contentType()->setSimpleType(BuiltinTypes::xsAnySimpleType); + } + } else if (baseType->isSimpleType()) { // 4 + complexType->contentType()->setSimpleType(baseType); + } else { // 5 + complexType->contentType()->setSimpleType(BuiltinTypes::xsAnySimpleType); + } +} + +void XsdSchemaResolver::resolveComplexContentComplexTypes() +{ + XsdComplexType::List complexTypes; + + // first collect the global complex types + const SchemaType::List types = m_schema->types(); + for (int i = 0; i < types.count(); ++i) { + if (types.at(i)->isComplexType() && types.at(i)->isDefinedBySchema()) + complexTypes.append(types.at(i)); + } + + // then collect all anonymous simple types + const SchemaType::List anonymousTypes = m_schema->anonymousTypes(); + for (int i = 0; i < anonymousTypes.count(); ++i) { + if (anonymousTypes.at(i)->isComplexType() && anonymousTypes.at(i)->isDefinedBySchema()) + complexTypes.append(anonymousTypes.at(i)); + } + + QSet visitedTypes; + for (int i = 0; i < complexTypes.count(); ++i) { + if (XsdComplexType::Ptr(complexTypes.at(i))->contentType()->variety() != XsdComplexType::ContentType::Simple) + resolveComplexContentComplexTypes(complexTypes.at(i), visitedTypes); + } +} + +void XsdSchemaResolver::resolveComplexContentComplexTypes(const XsdComplexType::Ptr &complexType, QSet &visitedTypes) +{ + if (visitedTypes.contains(complexType)) + return; + else + visitedTypes.insert(complexType); + + ComplexContentType item; + bool foundCorrespondingItem = false; + for (int i = 0; i < m_complexContentTypes.count(); ++i) { + if (m_complexContentTypes.at(i).complexType == complexType) { + item = m_complexContentTypes.at(i); + foundCorrespondingItem = true; + break; + } + } + + if (!foundCorrespondingItem) + return; + + const SchemaType::Ptr baseType = complexType->wxsSuperType(); + + // at this point simple types have been resolved already, so we care about + // complex types here only + if (baseType->isComplexType() && baseType->isDefinedBySchema()) + resolveComplexContentComplexTypes(XsdComplexType::Ptr(baseType), visitedTypes); + + + // @see http://www.w3.org/TR/xmlschema11-1/#dcl.ctd.ctcc.common + + // 3 + XsdParticle::Ptr effectiveContent; + if (!item.explicitContent) { // 3.1 + if (item.effectiveMixed == true) { // 3.1.1 + const XsdParticle::Ptr particle(new XsdParticle()); + particle->setMinimumOccurs(1); + particle->setMaximumOccurs(1); + particle->setMaximumOccursUnbounded(false); + + const XsdModelGroup::Ptr sequence(new XsdModelGroup()); + sequence->setCompositor(XsdModelGroup::SequenceCompositor); + particle->setTerm(sequence); + + effectiveContent = particle; + } else { // 3.1.2 + effectiveContent = XsdParticle::Ptr(); + } + } else { // 3.2 + effectiveContent = item.explicitContent; + } + + // 4 + XsdComplexType::ContentType::Ptr explicitContentType(new XsdComplexType::ContentType()); + if (item.complexType->derivationMethod() == XsdComplexType::DerivationRestriction) { // 4.1 + if (!effectiveContent) { // 4.1.1 + explicitContentType->setVariety(XsdComplexType::ContentType::Empty); + } else { // 4.1.2 + if (item.effectiveMixed == true) + explicitContentType->setVariety(XsdComplexType::ContentType::Mixed); + else + explicitContentType->setVariety(XsdComplexType::ContentType::ElementOnly); + + explicitContentType->setParticle(effectiveContent); + } + } else if (item.complexType->derivationMethod() == XsdComplexType::DerivationExtension) { // 4.2 + const SchemaType::Ptr baseType = item.complexType->wxsSuperType(); + if (baseType->isSimpleType() || (baseType->isComplexType() && baseType->isDefinedBySchema() && (XsdComplexType::Ptr(baseType)->contentType()->variety() == XsdComplexType::ContentType::Empty || + XsdComplexType::Ptr(baseType)->contentType()->variety() == XsdComplexType::ContentType::Simple))) { // 4.2.1 + if (!effectiveContent) { + explicitContentType->setVariety(XsdComplexType::ContentType::Empty); + } else { + if (item.effectiveMixed == true) + explicitContentType->setVariety(XsdComplexType::ContentType::Mixed); + else + explicitContentType->setVariety(XsdComplexType::ContentType::ElementOnly); + + explicitContentType->setParticle(effectiveContent); + } + } else if (baseType->isComplexType() && baseType->isDefinedBySchema() && (XsdComplexType::Ptr(baseType)->contentType()->variety() == XsdComplexType::ContentType::ElementOnly || + XsdComplexType::Ptr(baseType)->contentType()->variety() == XsdComplexType::ContentType::Mixed) && !effectiveContent) { // 4.2.2 + const XsdComplexType::Ptr complexBaseType(baseType); + + explicitContentType = complexBaseType->contentType(); + } else { // 4.2.3 + explicitContentType->setVariety(item.effectiveMixed ? XsdComplexType::ContentType::Mixed : XsdComplexType::ContentType::ElementOnly); + + XsdParticle::Ptr baseParticle; + if (baseType == BuiltinTypes::xsAnyType) { + // we need a workaround here, since the xsAnyType is no real (aka XsdComplexType) complex type... + + baseParticle = XsdParticle::Ptr(new XsdParticle()); + baseParticle->setMinimumOccurs(1); + baseParticle->setMaximumOccurs(1); + baseParticle->setMaximumOccursUnbounded(false); + + const XsdModelGroup::Ptr group(new XsdModelGroup()); + group->setCompositor(XsdModelGroup::SequenceCompositor); + + const XsdParticle::Ptr particle(new XsdParticle()); + particle->setMinimumOccurs(0); + particle->setMaximumOccursUnbounded(true); + + const XsdWildcard::Ptr wildcard(new XsdWildcard()); + wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Any); + wildcard->setProcessContents(XsdWildcard::Lax); + + particle->setTerm(wildcard); + XsdParticle::List particles; + particles.append(particle); + group->setParticles(particles); + baseParticle->setTerm(group); + } else { + const XsdComplexType::Ptr complexBaseType(baseType); + baseParticle = complexBaseType->contentType()->particle(); + } + if (baseParticle && baseParticle->term()->isModelGroup() && (XsdModelGroup::Ptr(baseParticle->term())->compositor() == XsdModelGroup::AllCompositor) && + (!item.explicitContent)) { // 4.2.3.1 + + explicitContentType->setParticle(baseParticle); + } else if (baseParticle && baseParticle->term()->isModelGroup() && (XsdModelGroup::Ptr(baseParticle->term())->compositor() == XsdModelGroup::AllCompositor) && + (effectiveContent->term()->isModelGroup() && (XsdModelGroup::Ptr(effectiveContent->term())->compositor() == XsdModelGroup::AllCompositor))) { // 4.2.3.2 + const XsdParticle::Ptr particle(new XsdParticle()); + particle->setMinimumOccurs(effectiveContent->minimumOccurs()); + particle->setMaximumOccurs(1); + particle->setMaximumOccursUnbounded(false); + + const XsdModelGroup::Ptr group(new XsdModelGroup()); + group->setCompositor(XsdModelGroup::AllCompositor); + XsdParticle::List particles = XsdModelGroup::Ptr(baseParticle->term())->particles(); + particles << XsdModelGroup::Ptr(effectiveContent->term())->particles(); + group->setParticles(particles); + particle->setTerm(group); + + explicitContentType->setParticle(particle); + } else { // 4.2.3.3 + const XsdParticle::Ptr particle(new XsdParticle()); + particle->setMinimumOccurs(1); + particle->setMaximumOccurs(1); + particle->setMaximumOccursUnbounded(false); + + const XsdModelGroup::Ptr group(new XsdModelGroup()); + group->setCompositor(XsdModelGroup::SequenceCompositor); + + if (effectiveContent && effectiveContent->term()->isModelGroup() && XsdModelGroup::Ptr(effectiveContent->term())->compositor() == XsdModelGroup::AllCompositor) { + m_context->error(QtXmlPatterns::tr("content model of complex type %1 contains %2 element so it cannot be derived by extension from a non-empty type") + .arg(formatType(m_namePool, complexType)).arg(formatKeyword("all")), XsdSchemaContext::XSDError, sourceLocation(complexType)); + return; + } + + if (baseParticle && baseParticle->term()->isModelGroup() && XsdModelGroup::Ptr(baseParticle->term())->compositor() == XsdModelGroup::AllCompositor) { + m_context->error(QtXmlPatterns::tr("complex type %1 cannot be derived by extension from %2 as the latter contains %3 element in its content model") + .arg(formatType(m_namePool, complexType)) + .arg(formatType(m_namePool, baseType)) + .arg(formatKeyword("all")), XsdSchemaContext::XSDError, sourceLocation(complexType)); + return; + } + + XsdParticle::List particles; + if (baseParticle) + particles << baseParticle; + if (effectiveContent) + particles << effectiveContent; + group->setParticles(particles); + particle->setTerm(group); + + explicitContentType->setParticle(particle); + } + + if (baseType->isDefinedBySchema()) { // xs:anyType has no open content + const XsdComplexType::Ptr complexBaseType(baseType); + explicitContentType->setOpenContent(complexBaseType->contentType()->openContent()); + } + } + } + + // 5 + XsdComplexType::OpenContent::Ptr wildcardElement; + if (item.complexType->contentType()->openContent()) { // 5.1 + wildcardElement = item.complexType->contentType()->openContent(); + } else { + if (m_defaultOpenContent) { // 5.2 + if ((explicitContentType->variety() != XsdComplexType::ContentType::Empty) || // 5.2.1 + (explicitContentType->variety() == XsdComplexType::ContentType::Empty && m_defaultOpenContentAppliesToEmpty)) { // 5.2.2 + wildcardElement = m_defaultOpenContent; + } + } + } + + // 6 + if (!wildcardElement) { // 6.1 + item.complexType->setContentType(explicitContentType); + } else { + if (wildcardElement->mode() == XsdComplexType::OpenContent::None) { // 6.2 + const XsdComplexType::ContentType::Ptr contentType(new XsdComplexType::ContentType()); + contentType->setVariety(explicitContentType->variety()); + contentType->setParticle(explicitContentType->particle()); + + item.complexType->setContentType(contentType); + } else { // 6.3 + const XsdComplexType::ContentType::Ptr contentType(new XsdComplexType::ContentType()); + + if (explicitContentType->variety() == XsdComplexType::ContentType::Empty) + contentType->setVariety(XsdComplexType::ContentType::ElementOnly); + else + contentType->setVariety(explicitContentType->variety()); + + if (explicitContentType->variety() == XsdComplexType::ContentType::Empty) { + const XsdParticle::Ptr particle(new XsdParticle()); + particle->setMinimumOccurs(1); + particle->setMaximumOccurs(1); + const XsdModelGroup::Ptr sequence(new XsdModelGroup()); + sequence->setCompositor(XsdModelGroup::SequenceCompositor); + particle->setTerm(sequence); + contentType->setParticle(particle); + } else { + contentType->setParticle(explicitContentType->particle()); + } + + const XsdComplexType::OpenContent::Ptr openContent(new XsdComplexType::OpenContent()); + if (wildcardElement) + openContent->setMode(wildcardElement->mode()); + else + openContent->setMode(XsdComplexType::OpenContent::Interleave); + + if (wildcardElement) + openContent->setWildcard(wildcardElement->wildcard()); + + item.complexType->setContentType(contentType); + } + } +} + +void XsdSchemaResolver::resolveAttributeTypes() +{ + for (int i = 0; i < m_attributeTypes.count(); ++i) { + const AttributeType item = m_attributeTypes.at(i); + + SchemaType::Ptr type = m_schema->type(item.typeName); + if (!type) { + // maybe it's a basic type... + type = m_context->schemaTypeFactory()->createSchemaType(item.typeName); + if (!type) { + m_context->error(QtXmlPatterns::tr("type %1 of %2 element cannot be resolved") + .arg(formatType(m_namePool, item.typeName)) + .arg(formatElement("attribute")), + XsdSchemaContext::XSDError, item.location); + return; + } + } + + if (!type->isSimpleType() && type->category() != SchemaType::None) { + m_context->error(QtXmlPatterns::tr("type of %1 element must be a simple type, %2 is not") + .arg(formatElement("attribute")) + .arg(formatType(m_namePool, item.typeName)), + XsdSchemaContext::XSDError, item.location); + return; + } + + item.attribute->setType(type); + } +} + +void XsdSchemaResolver::resolveAlternativeTypes() +{ + for (int i = 0; i < m_alternativeTypes.count(); ++i) { + const AlternativeType item = m_alternativeTypes.at(i); + + SchemaType::Ptr type = m_schema->type(item.typeName); + if (!type) { + // maybe it's a basic type... + type = m_context->schemaTypeFactory()->createSchemaType(item.typeName); + if (!type) { + m_context->error(QtXmlPatterns::tr("type %1 of %2 element cannot be resolved") + .arg(formatType(m_namePool, item.typeName)) + .arg(formatElement("alternative")), + XsdSchemaContext::XSDError, item.location); + return; + } + } + + item.alternative->setType(type); + } + + for (int i = 0; i < m_alternativeTypeElements.count(); ++i) { + const AlternativeTypeElement item = m_alternativeTypeElements.at(i); + item.alternative->setType(item.element->type()); + } +} + +bool hasCircularSubstitutionGroup(const XsdElement::Ptr ¤t, const XsdElement::Ptr &head, const NamePool::Ptr &namePool) +{ + if (current == head) + return true; + else { + const XsdElement::List elements = current->substitutionGroupAffiliations(); + for (int i = 0; i < elements.count(); ++i) { + if (hasCircularSubstitutionGroup(elements.at(i), head, namePool)) + return true; + } + } + + return false; +} + +void XsdSchemaResolver::resolveSubstitutionGroupAffiliations() +{ + for (int i = 0; i < m_substitutionGroupAffiliations.count(); ++i) { + const SubstitutionGroupAffiliation item = m_substitutionGroupAffiliations.at(i); + + XsdElement::List affiliations; + for (int j = 0; j < item.elementNames.count(); ++j) { + const XsdElement::Ptr element = m_schema->element(item.elementNames.at(j)); + if (!element) { + m_context->error(QtXmlPatterns::tr("substitution group %1 of %2 element cannot be resolved") + .arg(formatKeyword(m_namePool, item.elementNames.at(j))) + .arg(formatElement("element")), + XsdSchemaContext::XSDError, item.location); + return; + } + + // @see http://www.w3.org/TR/xmlschema11-1/#e-props-correct 5) + if (hasCircularSubstitutionGroup(element, item.element, m_namePool)) { + m_context->error(QtXmlPatterns::tr("substitution group %1 has circular definition").arg(formatKeyword(m_namePool, item.elementNames.at(j))), XsdSchemaContext::XSDError, item.location); + return; + } + + affiliations.append(element); + } + + item.element->setSubstitutionGroupAffiliations(affiliations); + } + + for (int i = 0; i < m_substitutionGroupTypes.count(); ++i) { + const XsdElement::Ptr element = m_substitutionGroupTypes.at(i); + element->setType(element->substitutionGroupAffiliations().first()->type()); + } +} + +bool isSubstGroupHeadOf(const XsdElement::Ptr &head, const XsdElement::Ptr &element, const NamePool::Ptr &namePool) +{ + if (head->name(namePool) == element->name(namePool)) + return true; + + const XsdElement::List affiliations = element->substitutionGroupAffiliations(); + for (int i = 0; i < affiliations.count(); ++i) { + if (isSubstGroupHeadOf(head, affiliations.at(i), namePool)) + return true; + } + + return false; +} + +void XsdSchemaResolver::resolveSubstitutionGroups() +{ + const XsdElement::List elements = m_schema->elements(); + for (int i = 0; i < elements.count(); ++i) { + const XsdElement::Ptr element = elements.at(i); + + // the element is always itself in the substitution group + element->addSubstitutionGroup(element); + + for (int j = 0; j < elements.count(); ++j) { + if (i == j) + continue; + + if (isSubstGroupHeadOf(element, elements.at(j), m_namePool)) + element->addSubstitutionGroup(elements.at(j)); + } + } +} + +void XsdSchemaResolver::resolveTermReferences() +{ + // first the global complex types + const SchemaType::List types = m_schema->types(); + for (int i = 0; i < types.count(); ++i) { + if (!(types.at(i)->isComplexType()) || !types.at(i)->isDefinedBySchema()) + continue; + + const XsdComplexType::Ptr complexType = types.at(i); + if (complexType->contentType()->variety() != XsdComplexType::ContentType::ElementOnly && complexType->contentType()->variety() != XsdComplexType::ContentType::Mixed) + continue; + + resolveTermReference(complexType->contentType()->particle(), QSet()); + } + + // then all anonymous complex types + const SchemaType::List anonymousTypes = m_schema->anonymousTypes(); + for (int i = 0; i < anonymousTypes.count(); ++i) { + if (!(anonymousTypes.at(i)->isComplexType()) || !anonymousTypes.at(i)->isDefinedBySchema()) + continue; + + const XsdComplexType::Ptr complexType = anonymousTypes.at(i); + if (complexType->contentType()->variety() != XsdComplexType::ContentType::ElementOnly && complexType->contentType()->variety() != XsdComplexType::ContentType::Mixed) + continue; + + resolveTermReference(complexType->contentType()->particle(), QSet()); + } + + const XsdModelGroup::List groups = m_schema->elementGroups(); + for (int i = 0; i < groups.count(); ++i) { + const XsdParticle::Ptr particle(new XsdParticle()); + particle->setTerm(groups.at(i)); + resolveTermReference(particle, QSet()); + } +} + +void XsdSchemaResolver::resolveTermReference(const XsdParticle::Ptr &particle, QSet visitedGroups) +{ + if (!particle) + return; + + const XsdTerm::Ptr term = particle->term(); + + // if it is a model group, we iterate over it recursive... + if (term->isModelGroup()) { + const XsdModelGroup::Ptr modelGroup = term; + const XsdParticle::List particles = modelGroup->particles(); + + for (int i = 0; i < particles.count(); ++i) { + resolveTermReference(particles.at(i), visitedGroups); + } + + // check for unique names of elements inside all compositor + if (modelGroup->compositor() != XsdModelGroup::ChoiceCompositor) { + for (int i = 0; i < particles.count(); ++i) { + const XsdParticle::Ptr particle = particles.at(i); + const XsdTerm::Ptr term = particle->term(); + + if (!(term->isElement())) + continue; + + for (int j = 0; j < particles.count(); ++j) { + const XsdParticle::Ptr otherParticle = particles.at(j); + const XsdTerm::Ptr otherTerm = otherParticle->term(); + + if (otherTerm->isElement() && i != j) { + const XsdElement::Ptr element = term; + const XsdElement::Ptr otherElement = otherTerm; + + if (element->name(m_namePool) == otherElement->name(m_namePool)) { + if (modelGroup->compositor() == XsdModelGroup::AllCompositor) { + m_context->error(QtXmlPatterns::tr("duplicated element names %1 in %2 element") + .arg(formatKeyword(element->displayName(m_namePool))) + .arg(formatElement("all")), + XsdSchemaContext::XSDError, sourceLocation(modelGroup)); + return; + } else if (modelGroup->compositor() == XsdModelGroup::SequenceCompositor) { + if (element->type() != otherElement->type()) { // not same variety + m_context->error(QtXmlPatterns::tr("duplicated element names %1 in %2 element") + .arg(formatKeyword(element->displayName(m_namePool))) + .arg(formatElement("sequence")), + XsdSchemaContext::XSDError, sourceLocation(modelGroup)); + return; + } + } + } + } + } + } + } + + return; + } + + // ...otherwise we have reached the end of recursion... + if (!term->isReference()) + return; + + // ...or we have reached a reference term that must be resolved + const XsdReference::Ptr reference = term; + switch (reference->type()) { + case XsdReference::Element: + { + const XsdElement::Ptr element = m_schema->element(reference->referenceName()); + if (element) { + particle->setTerm(element); + } else { + m_context->error(QtXmlPatterns::tr("reference %1 of %2 element cannot be resolved") + .arg(formatKeyword(m_namePool, reference->referenceName())) + .arg(formatElement("element")), + XsdSchemaContext::XSDError, reference->sourceLocation()); + return; + } + } + break; + case XsdReference::ModelGroup: + { + const XsdModelGroup::Ptr modelGroup = m_schema->elementGroup(reference->referenceName()); + if (modelGroup) { + if (visitedGroups.contains(modelGroup->name(m_namePool))) { + m_context->error(QtXmlPatterns::tr("circular group reference for %1").arg(formatKeyword(modelGroup->displayName(m_namePool))), + XsdSchemaContext::XSDError, reference->sourceLocation()); + } else { + visitedGroups.insert(modelGroup->name(m_namePool)); + } + + particle->setTerm(modelGroup); + + // start recursive iteration here as well to get all references resolved + const XsdParticle::List particles = modelGroup->particles(); + for (int i = 0; i < particles.count(); ++i) { + resolveTermReference(particles.at(i), visitedGroups); + } + + if (modelGroup->compositor() == XsdModelGroup::AllCompositor) { + if (m_allGroups.contains(reference)) { + m_context->error(QtXmlPatterns::tr("%1 element is not allowed in this scope").arg(formatElement("all")), + XsdSchemaContext::XSDError, reference->sourceLocation()); + return; + } + if (particle->maximumOccursUnbounded() || particle->maximumOccurs() != 1) { + m_context->error(QtXmlPatterns::tr("%1 element cannot have %2 attribute with value other than %3") + .arg(formatElement("all")) + .arg(formatAttribute("maxOccurs")) + .arg(formatData("1")), + XsdSchemaContext::XSDError, reference->sourceLocation()); + return; + } + if (particle->minimumOccurs() != 0 && particle->minimumOccurs() != 1) { + m_context->error(QtXmlPatterns::tr("%1 element cannot have %2 attribute with value other than %3 or %4") + .arg(formatElement("all")) + .arg(formatAttribute("minOccurs")) + .arg(formatData("0")) + .arg(formatData("1")), + XsdSchemaContext::XSDError, reference->sourceLocation()); + return; + } + } + } else { + m_context->error(QtXmlPatterns::tr("reference %1 of %2 element cannot be resolved") + .arg(formatKeyword(m_namePool, reference->referenceName())) + .arg(formatElement("group")), + XsdSchemaContext::XSDError, reference->sourceLocation()); + return; + } + } + break; + } +} + +void XsdSchemaResolver::resolveAttributeTermReferences() +{ + // first all global attribute groups + const XsdAttributeGroup::List attributeGroups = m_schema->attributeGroups(); + for (int i = 0; i < attributeGroups.count(); ++i) { + XsdWildcard::Ptr wildcard = attributeGroups.at(i)->wildcard(); + const XsdAttributeUse::List uses = resolveAttributeTermReferences(attributeGroups.at(i)->attributeUses(), wildcard, QSet()); + attributeGroups.at(i)->setAttributeUses(uses); + attributeGroups.at(i)->setWildcard(wildcard); + } + + // then the global complex types + const SchemaType::List types = m_schema->types(); + for (int i = 0; i < types.count(); ++i) { + if (!(types.at(i)->isComplexType()) || !types.at(i)->isDefinedBySchema()) + continue; + + const XsdComplexType::Ptr complexType = types.at(i); + const XsdAttributeUse::List attributeUses = complexType->attributeUses(); + + XsdWildcard::Ptr wildcard = complexType->attributeWildcard(); + const XsdAttributeUse::List uses = resolveAttributeTermReferences(attributeUses, wildcard, QSet()); + complexType->setAttributeUses(uses); + complexType->setAttributeWildcard(wildcard); + } + + // and afterwards all anonymous complex types + const SchemaType::List anonymousTypes = m_schema->anonymousTypes(); + for (int i = 0; i < anonymousTypes.count(); ++i) { + if (!(anonymousTypes.at(i)->isComplexType()) || !anonymousTypes.at(i)->isDefinedBySchema()) + continue; + + const XsdComplexType::Ptr complexType = anonymousTypes.at(i); + const XsdAttributeUse::List attributeUses = complexType->attributeUses(); + + XsdWildcard::Ptr wildcard = complexType->attributeWildcard(); + const XsdAttributeUse::List uses = resolveAttributeTermReferences(attributeUses, wildcard, QSet()); + complexType->setAttributeUses(uses); + complexType->setAttributeWildcard(wildcard); + } +} + +XsdAttributeUse::List XsdSchemaResolver::resolveAttributeTermReferences(const XsdAttributeUse::List &attributeUses, XsdWildcard::Ptr &wildcard, QSet visitedAttributeGroups) +{ + XsdAttributeUse::List resolvedAttributeUses; + + for (int i = 0; i < attributeUses.count(); ++i) { + const XsdAttributeUse::Ptr attributeUse = attributeUses.at(i); + if (attributeUse->isAttributeUse()) { + // it is a real attribute use, so no need to resolve it + resolvedAttributeUses.append(attributeUse); + } else if (attributeUse->isReference()) { + // it is just a reference, so resolve it to the real attribute use + + const XsdAttributeReference::Ptr reference = attributeUse; + if (reference->type() == XsdAttributeReference::AttributeUse) { + + // lookup the real attribute + const XsdAttribute::Ptr attribute = m_schema->attribute(reference->referenceName()); + if (!attribute) { + m_context->error(QtXmlPatterns::tr("reference %1 of %2 element cannot be resolved") + .arg(formatKeyword(m_namePool, reference->referenceName())) + .arg(formatElement("attribute")), + XsdSchemaContext::XSDError, reference->sourceLocation()); + return XsdAttributeUse::List(); + } + + // if both, reference and definition have a fixed or default value set, then they must be equal + if (attribute->valueConstraint() && attributeUse->valueConstraint()) { + if (attribute->valueConstraint()->value() != attributeUse->valueConstraint()->value()) { + m_context->error(QtXmlPatterns::tr("%1 or %2 attribute of reference %3 does not match with the attribute declaration %4") + .arg(formatAttribute("fixed")) + .arg(formatAttribute("default")) + .arg(formatKeyword(m_namePool, reference->referenceName())) + .arg(formatKeyword(attribute->displayName(m_namePool))), + XsdSchemaContext::XSDError, reference->sourceLocation()); + return XsdAttributeUse::List(); + } + } + + attributeUse->setAttribute(attribute); + if (!attributeUse->valueConstraint() && attribute->valueConstraint()) + attributeUse->setValueConstraint(XsdAttributeUse::ValueConstraint::fromAttributeValueConstraint(attribute->valueConstraint())); + + resolvedAttributeUses.append(attributeUse); + } else if (reference->type() == XsdAttributeReference::AttributeGroup) { + const XsdAttributeGroup::Ptr attributeGroup = m_schema->attributeGroup(reference->referenceName()); + if (!attributeGroup) { + m_context->error(QtXmlPatterns::tr("reference %1 of %2 element cannot be resolved") + .arg(formatKeyword(m_namePool, reference->referenceName())) + .arg(formatElement("attributeGroup")), + XsdSchemaContext::XSDError, reference->sourceLocation()); + return XsdAttributeUse::List(); + } + if (visitedAttributeGroups.contains(attributeGroup->name(m_namePool))) { + m_context->error(QtXmlPatterns::tr("attribute group %1 has circular reference").arg(formatKeyword(m_namePool, reference->referenceName())), + XsdSchemaContext::XSDError, reference->sourceLocation()); + return XsdAttributeUse::List(); + } else { + visitedAttributeGroups.insert(attributeGroup->name(m_namePool)); + } + + // resolve attribute wildcards as defined in http://www.w3.org/TR/xmlschema11-1/#declare-attributeGroup-wildcard + XsdWildcard::Ptr childWildcard; + resolvedAttributeUses << resolveAttributeTermReferences(attributeGroup->attributeUses(), childWildcard, visitedAttributeGroups); + if (!childWildcard) { + if (attributeGroup->wildcard()) { + if (wildcard) { + const XsdWildcard::ProcessContents contents = wildcard->processContents(); + wildcard = XsdSchemaHelper::wildcardIntersection(wildcard, attributeGroup->wildcard()); + wildcard->setProcessContents(contents); + } else { + wildcard = attributeGroup->wildcard(); + } + } + } else { + XsdWildcard::Ptr newWildcard; + if (attributeGroup->wildcard()) { + const XsdWildcard::ProcessContents contents = attributeGroup->wildcard()->processContents(); + newWildcard = XsdSchemaHelper::wildcardIntersection(attributeGroup->wildcard(), childWildcard); + newWildcard->setProcessContents(contents); + } else { + newWildcard = childWildcard; + } + + if (wildcard) { + const XsdWildcard::ProcessContents contents = wildcard->processContents(); + wildcard = XsdSchemaHelper::wildcardIntersection(wildcard, newWildcard); + wildcard->setProcessContents(contents); + } else { + wildcard = newWildcard; + } + } + } + } + } + + return resolvedAttributeUses; +} + +void XsdSchemaResolver::resolveAttributeInheritance() +{ + // collect the global and anonymous complex types + SchemaType::List types = m_schema->types(); + types << m_schema->anonymousTypes(); + + QSet visitedTypes; + for (int i = 0; i < types.count(); ++i) { + if (!(types.at(i)->isComplexType()) || !types.at(i)->isDefinedBySchema()) + continue; + + const XsdComplexType::Ptr complexType = types.at(i); + + resolveAttributeInheritance(complexType, visitedTypes); + } +} + +bool isValidWildcardRestriction(const XsdWildcard::Ptr &wildcard, const XsdWildcard::Ptr &baseWildcard) +{ + if (wildcard->namespaceConstraint()->variety() == baseWildcard->namespaceConstraint()->variety()) { + if (!XsdSchemaHelper::checkWildcardProcessContents(baseWildcard, wildcard)) + return false; + } + + if (wildcard->namespaceConstraint()->variety() == XsdWildcard::NamespaceConstraint::Any && + baseWildcard->namespaceConstraint()->variety() != XsdWildcard::NamespaceConstraint::Any ) { + return false; + } + if (baseWildcard->namespaceConstraint()->variety() == XsdWildcard::NamespaceConstraint::Not && + wildcard->namespaceConstraint()->variety() == XsdWildcard::NamespaceConstraint::Enumeration) { + if (!baseWildcard->namespaceConstraint()->namespaces().intersect(wildcard->namespaceConstraint()->namespaces()).isEmpty()) + return false; + } + if (baseWildcard->namespaceConstraint()->variety() == XsdWildcard::NamespaceConstraint::Enumeration && + wildcard->namespaceConstraint()->variety() == XsdWildcard::NamespaceConstraint::Enumeration) { + if (!wildcard->namespaceConstraint()->namespaces().subtract(baseWildcard->namespaceConstraint()->namespaces()).isEmpty()) + return false; + } + + return true; +} + +/* + * Since we inherit the attributes from our base class we have to walk up in the + * inheritance hierarchy first and resolve the attribute inheritance top-down. + */ +void XsdSchemaResolver::resolveAttributeInheritance(const XsdComplexType::Ptr &complexType, QSet &visitedTypes) +{ + if (visitedTypes.contains(complexType)) + return; + else + visitedTypes.insert(complexType); + + const SchemaType::Ptr baseType = complexType->wxsSuperType(); + Q_ASSERT(baseType); + + if (!(baseType->isComplexType()) || !baseType->isDefinedBySchema()) + return; + + const XsdComplexType::Ptr complexBaseType = baseType; + + resolveAttributeInheritance(complexBaseType, visitedTypes); + + // @see http://www.w3.org/TR/xmlschema11-1/#dcl.ctd.attuses + + // 1 and 2 (the attribute groups have been resolved here already) + const XsdAttributeUse::List uses = complexBaseType->attributeUses(); + + if (complexType->derivationMethod() == XsdComplexType::DerivationRestriction) { // 3.2 + const XsdAttributeUse::List currentUses = complexType->attributeUses(); + + // 3.2.1 and 3.2.2 As we also keep the prohibited attributes as objects, the algorithm below + // handles both the same way + + // add only these attribute uses of the base type that match one of the following criteria: + // 1: there is no attribute use with the same name in type + // 2: there is no attribute with the same name marked as prohibited in type + for (int j = 0; j < uses.count(); ++j) { + const XsdAttributeUse::Ptr use = uses.at(j); + bool found = false; + for (int k = 0; k < currentUses.count(); ++k) { + if (use->attribute()->name(m_namePool) == currentUses.at(k)->attribute()->name(m_namePool)) { + found = true; + + // check if prohibited usage is violated + if ((use->useType() == XsdAttributeUse::ProhibitedUse) && (currentUses.at(k)->useType() != XsdAttributeUse::ProhibitedUse)) { + m_context->error(QtXmlPatterns::tr("%1 attribute in %2 must have %3 use like in base type %4") + .arg(formatAttribute(use->attribute()->displayName(m_namePool))) + .arg(formatType(m_namePool, complexType)) + .arg(formatData("prohibited")) + .arg(formatType(m_namePool, complexBaseType)), + XsdSchemaContext::XSDError, sourceLocation(complexType)); + return; + } + + break; + } + } + + if (!found && uses.at(j)->useType() != XsdAttributeUse::ProhibitedUse) { + complexType->addAttributeUse(uses.at(j)); + } + } + } else if (complexType->derivationMethod() == XsdComplexType::DerivationExtension) { // 3.1 + QHash availableUses; + + // fill hash with attribute uses of current type for faster lookup + { + const XsdAttributeUse::List attributeUses = complexType->attributeUses(); + + for (int i = 0; i < attributeUses.count(); ++i) { + availableUses.insert(attributeUses.at(i)->attribute()->name(m_namePool), attributeUses.at(i)); + } + } + + // just add the attribute uses of the base type + for (int i = 0; i < uses.count(); ++i) { + const XsdAttributeUse::Ptr currentAttributeUse = uses.at(i); + + // if the base type defines the attribute as prohibited but we override it in current type, then don't copy the prohibited attribute use + if ((currentAttributeUse->useType() == XsdAttributeUse::ProhibitedUse) && availableUses.contains(currentAttributeUse->attribute()->name(m_namePool))) + continue; + + complexType->addAttributeUse(uses.at(i)); + } + } + + // handle attribute wildcards: @see http://www.w3.org/TR/xmlschema11-1/#dcl.ctd.anyatt + + // 1 + const XsdWildcard::Ptr completeWildcard(complexType->attributeWildcard()); + + if (complexType->derivationMethod() == XsdComplexType::DerivationRestriction) { + if (complexType->wxsSuperType()->isComplexType() && complexType->wxsSuperType()->isDefinedBySchema()) { + const XsdComplexType::Ptr complexBaseType(complexType->wxsSuperType()); + if (complexType->attributeWildcard()) { + if (complexBaseType->attributeWildcard()) { + if (!isValidWildcardRestriction(complexType->attributeWildcard(), complexBaseType->attributeWildcard())) { + m_context->error(QtXmlPatterns::tr("attribute wildcard of %1 is not a valid restriction of attribute wildcard of base type %2") + .arg(formatType(m_namePool, complexType)) + .arg(formatType(m_namePool, complexBaseType)), + XsdSchemaContext::XSDError, sourceLocation(complexType)); + return; + } + } else { + m_context->error(QtXmlPatterns::tr("%1 has attribute wildcard but its base type %2 has not") + .arg(formatType(m_namePool, complexType)) + .arg(formatType(m_namePool, complexBaseType)), + XsdSchemaContext::XSDError, sourceLocation(complexType)); + return; + } + } + } + complexType->setAttributeWildcard(completeWildcard); // 2.1 + } else if (complexType->derivationMethod() == XsdComplexType::DerivationExtension) { + XsdWildcard::Ptr baseWildcard; // 2.2.1 + if (complexType->wxsSuperType()->isComplexType() && complexType->wxsSuperType()->isDefinedBySchema()) + baseWildcard = XsdComplexType::Ptr(complexType->wxsSuperType())->attributeWildcard(); // 2.2.1.1 + else + baseWildcard = XsdWildcard::Ptr(); // 2.2.1.2 + + if (!baseWildcard) { + complexType->setAttributeWildcard(completeWildcard); // 2.2.2.1 + } else if (!completeWildcard) { + complexType->setAttributeWildcard(baseWildcard); // 2.2.2.2 + } else { + XsdWildcard::Ptr unionWildcard = XsdSchemaHelper::wildcardUnion(completeWildcard, baseWildcard); + if (unionWildcard) { + unionWildcard->setProcessContents(completeWildcard->processContents()); + complexType->setAttributeWildcard(unionWildcard); // 2.2.2.3 + } else { + m_context->error(QtXmlPatterns::tr("union of attribute wildcard of type %1 and attribute wildcard of its base type %2 is not expressible") + .arg(formatType(m_namePool, complexType)) + .arg(formatType(m_namePool, complexBaseType)), + XsdSchemaContext::XSDError, sourceLocation(complexType)); + return; + } + } + } +} + +void XsdSchemaResolver::resolveEnumerationFacetValues() +{ + XsdSimpleType::List simpleTypes; + + // first collect the global simple types + const SchemaType::List types = m_schema->types(); + for (int i = 0; i < types.count(); ++i) { + if (types.at(i)->isSimpleType()) + simpleTypes.append(types.at(i)); + } + + // then collect all anonymous simple types + const SchemaType::List anonymousTypes = m_schema->anonymousTypes(); + for (int i = 0; i < anonymousTypes.count(); ++i) { + if (anonymousTypes.at(i)->isSimpleType()) + simpleTypes.append(anonymousTypes.at(i)); + } + // process all simple types + for (int i = 0; i < simpleTypes.count(); ++i) { + const XsdSimpleType::Ptr simpleType = simpleTypes.at(i); + + // we resolve the enumeration values only for xs:QName and xs:NOTATION based types + if (BuiltinTypes::xsQName->wxsTypeMatches(simpleType) || + BuiltinTypes::xsNOTATION->wxsTypeMatches(simpleType)) { + const XsdFacet::Hash facets = simpleType->facets(); + if (facets.contains(XsdFacet::Enumeration)) { + AtomicValue::List newValues; + + const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration); + const AtomicValue::List values = facet->multiValue(); + for (int j = 0; j < values.count(); ++j) { + const AtomicValue::Ptr value = values.at(j); + + Q_ASSERT(m_enumerationFacetValues.contains(value)); + const NamespaceSupport support( m_enumerationFacetValues.value(value) ); + + const QString qualifiedName = value->as >()->stringValue(); + if (!XPathHelper::isQName(qualifiedName)) { + m_context->error(QtXmlPatterns::tr("enumeration facet contains invalid content: {%1} is not a value of type %2") + .arg(formatData(qualifiedName)) + .arg(formatType(m_namePool, BuiltinTypes::xsQName)), + XsdSchemaContext::XSDError, sourceLocation(simpleType)); + return; + } + + QXmlName qNameValue; + bool result = support.processName(qualifiedName, NamespaceSupport::ElementName, qNameValue); + if (!result) { + m_context->error(QtXmlPatterns::tr("namespace prefix of qualified name %1 is not defined").arg(formatData(qualifiedName)), + XsdSchemaContext::XSDError, sourceLocation(simpleType)); + return; + } + + newValues.append(QNameValue::fromValue(m_namePool, qNameValue)); + } + facet->setMultiValue(newValues); + } + } + } +} + +QSourceLocation XsdSchemaResolver::sourceLocation(const NamedSchemaComponent::Ptr component) const +{ + if (m_componentLocationHash.contains(component)) { + return m_componentLocationHash.value(component); + } else { + QSourceLocation location; + location.setLine(1); + location.setColumn(1); + location.setUri(QString::fromLatin1("dummyUri")); + + return location; + } +} + +XsdFacet::Hash XsdSchemaResolver::complexTypeFacets(const XsdComplexType::Ptr &complexType) const +{ + for (int i = 0; i < m_complexBaseTypes.count(); ++i) { + if (m_complexBaseTypes.at(i).complexType == complexType) + return m_complexBaseTypes.at(i).facets; + } + + return XsdFacet::Hash(); +} + +void XsdSchemaResolver::checkRedefinedGroups() +{ + for (int i = 0; i < m_redefinedGroups.count(); ++i) { + const RedefinedGroups item = m_redefinedGroups.at(i); + + // create dummy particles... + const XsdParticle::Ptr redefinedParticle(new XsdParticle()); + redefinedParticle->setTerm(item.redefinedGroup); + const XsdParticle::Ptr particle(new XsdParticle()); + particle->setTerm(item.group); + + // so that we can pass them to XsdParticleChecker::subsumes() + QString errorMsg; + if (!XsdParticleChecker::subsumes(particle, redefinedParticle, m_context, errorMsg)) { + m_context->error(QtXmlPatterns::tr("%1 element %2 is not a valid restriction of the %3 element it redefines: %4") + .arg(formatElement("group")) + .arg(formatData(item.redefinedGroup->displayName(m_namePool))) + .arg(formatElement("group")) + .arg(errorMsg), + XsdSchemaContext::XSDError, sourceLocation(item.redefinedGroup)); + return; + } + } +} + +void XsdSchemaResolver::checkRedefinedAttributeGroups() +{ + for (int i = 0; i < m_redefinedAttributeGroups.count(); ++i) { + const RedefinedAttributeGroups item = m_redefinedAttributeGroups.at(i); + + QString errorMsg; + if (!XsdSchemaHelper::isValidAttributeGroupRestriction(item.redefinedGroup, item.group, m_context, errorMsg)) { + m_context->error(QtXmlPatterns::tr("%1 element %2 is not a valid restriction of the %3 element it redefines: %4") + .arg(formatElement("attributeGroup")) + .arg(formatData(item.redefinedGroup->displayName(m_namePool))) + .arg(formatElement("attributeGroup")) + .arg(errorMsg), + XsdSchemaContext::XSDError, sourceLocation(item.redefinedGroup)); + return; + } + } +} + +AnySimpleType::Ptr XsdSchemaResolver::findPrimitiveType(const AnySimpleType::Ptr &type, QSet &visitedTypes) +{ + if (visitedTypes.contains(type)) { + // found invalid circular reference... + return AnySimpleType::Ptr(); + } else { + visitedTypes.insert(type); + } + + const QXmlName typeName = type->name(m_namePool); + if (typeName == BuiltinTypes::xsString->name(m_namePool) || + typeName == BuiltinTypes::xsBoolean->name(m_namePool) || + typeName == BuiltinTypes::xsFloat->name(m_namePool) || + typeName == BuiltinTypes::xsDouble->name(m_namePool) || + typeName == BuiltinTypes::xsDecimal->name(m_namePool) || + typeName == BuiltinTypes::xsDuration->name(m_namePool) || + typeName == BuiltinTypes::xsDateTime->name(m_namePool) || + typeName == BuiltinTypes::xsTime->name(m_namePool) || + typeName == BuiltinTypes::xsDate->name(m_namePool) || + typeName == BuiltinTypes::xsGYearMonth->name(m_namePool) || + typeName == BuiltinTypes::xsGYear->name(m_namePool) || + typeName == BuiltinTypes::xsGMonthDay->name(m_namePool) || + typeName == BuiltinTypes::xsGDay->name(m_namePool) || + typeName == BuiltinTypes::xsGMonth->name(m_namePool) || + typeName == BuiltinTypes::xsHexBinary->name(m_namePool) || + typeName == BuiltinTypes::xsBase64Binary->name(m_namePool) || + typeName == BuiltinTypes::xsAnyURI->name(m_namePool) || + typeName == BuiltinTypes::xsQName->name(m_namePool) || + typeName == BuiltinTypes::xsNOTATION->name(m_namePool) || + typeName == BuiltinTypes::xsAnySimpleType->name(m_namePool)) + return type; + else { + if (type->wxsSuperType()) + return findPrimitiveType(type->wxsSuperType(), visitedTypes); + else { + return AnySimpleType::Ptr(); + } + } +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdschemaresolver_p.h b/src/xmlpatterns/schema/qxsdschemaresolver_p.h new file mode 100644 index 0000000..1222619 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdschemaresolver_p.h @@ -0,0 +1,548 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdSchemaResolver_H +#define Patternist_XsdSchemaResolver_H + +#include "qnamespacesupport_p.h" +#include "qschematype_p.h" +#include "qschematypefactory_p.h" +#include "qxsdalternative_p.h" +#include "qxsdattribute_p.h" +#include "qxsdattributegroup_p.h" +#include "qxsdelement_p.h" +#include "qxsdmodelgroup_p.h" +#include "qxsdnotation_p.h" +#include "qxsdreference_p.h" +#include "qxsdschema_p.h" +#include "qxsdschemachecker_p.h" +#include "qxsdsimpletype_p.h" + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + class XsdSchemaContext; + class XsdSchemaParserContext; + + /** + * @short Encapsulates the resolving of type/element references in a schema after parsing has finished. + * + * This class collects task for resolving types or element references. After the parsing has finished, + * one can start the resolve process by calling resolve(). + * + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdSchemaResolver : public QSharedData + { + public: + typedef QExplicitlySharedDataPointer Ptr; + + /** + * Creates a new schema resolver. + * + * @param context The schema context used for error reporting etc.. + * @param parserContext The schema parser context where all objects to resolve belong to. + */ + XsdSchemaResolver(const QExplicitlySharedDataPointer &context, const XsdSchemaParserContext *parserContext); + + /** + * Destroys the schema resolver. + */ + ~XsdSchemaResolver(); + + /** + * Starts the resolve process. + */ + void resolve(); + + /** + * Adds a resolve task for key references. + * + * The resolver will try to set the referencedKey property of @p keyRef to the key or unique object + * of @p element that has the given @p name. + */ + void addKeyReference(const XsdElement::Ptr &element, const XsdIdentityConstraint::Ptr &keyRef, const QXmlName &name, const QSourceLocation &location); + + /** + * Adds a resolve task for the base type of restriction of a simple type. + * + * The resolver will set the base type of @p simpleType to the type named by @p baseName. + */ + void addSimpleRestrictionBase(const XsdSimpleType::Ptr &simpleType, const QXmlName &baseName, const QSourceLocation &location); + + /** + * Removes the resolve task for the base type of restriction of the simple @p type. + */ + void removeSimpleRestrictionBase(const XsdSimpleType::Ptr &type); + + /** + * Adds a resolve task for the list type of a simple type. + * + * The resolver will set the itemType property of @p simpleType to the type named by @p typeName. + */ + void addSimpleListType(const XsdSimpleType::Ptr &simpleType, const QXmlName &typeName, const QSourceLocation &location); + + /** + * Adds a resolve task for the member types of a simple type. + * + * The resolver will set the memberTypes property of @p simpleType to the types named by @p typeNames. + */ + void addSimpleUnionTypes(const XsdSimpleType::Ptr &simpleType, const QList &typeNames, const QSourceLocation &location); + + /** + * Adds a resolve task for the type of an element. + * + * The resolver will set the type of the @p element to the type named by @p typeName. + */ + void addElementType(const XsdElement::Ptr &element, const QXmlName &typeName, const QSourceLocation &location); + + /** + * Adds a resolve task for the base type of a complex type. + * + * The resolver will set the base type of @p complexType to the type named by @p baseName. + */ + void addComplexBaseType(const XsdComplexType::Ptr &complexType, const QXmlName &baseName, const QSourceLocation &location, const XsdFacet::Hash &facets = XsdFacet::Hash()); + + /** + * Removes the resolve task for the base type of the complex @p type. + */ + void removeComplexBaseType(const XsdComplexType::Ptr &type); + + /** + * Adds a resolve task for the content type of a complex type. + * + * The resolver will set the content type properties for @p complexType based on the + * given explicit @p content and effective @p mixed value. + */ + void addComplexContentType(const XsdComplexType::Ptr &complexType, const XsdParticle::Ptr &content, bool mixed); + + /** + * Adds a resolve task for the type of an attribute. + * + * The resolver will set the type of the @p attribute to the type named by @p typeName. + */ + void addAttributeType(const XsdAttribute::Ptr &attribute, const QXmlName &typeName, const QSourceLocation &location); + + /** + * Adds a resolve task for the type of an alternative. + * + * The resolver will set the type of the @p alternative to the type named by @p typeName. + */ + void addAlternativeType(const XsdAlternative::Ptr &alternative, const QXmlName &typeName, const QSourceLocation &location); + + /** + * Adds a resolve task for the type of an alternative. + * + * The resolver will set the type of the @p alternative to the type of the @p element after + * the type of the @p element has been resolved. + */ + void addAlternativeType(const XsdAlternative::Ptr &alternative, const XsdElement::Ptr &element); + + /** + * Adds a resolve task for the substituion group affiliations of an element. + * + * The resolver will set the substitution group affiliations of the @p element to the + * top-level element named by @p elementNames. + */ + void addSubstitutionGroupAffiliation(const XsdElement::Ptr &element, const QList &elementName, const QSourceLocation &location); + + /** + * Adds a resolve task for an element that has no type specified, only a substitution group + * affiliation. + * + * The resolver will set the type of the substitution group affiliation as type for the element. + */ + void addSubstitutionGroupType(const XsdElement::Ptr &element); + + /** + * Adds the component location hash, so the resolver is able to report meaning full + * error messages. + */ + void addComponentLocationHash(const QHash &hash); + + /** + * Add a resolve task for enumeration facet values. + * + * In case the enumeration is of type QName or NOTATION, we have to resolve the QName later, + * so we store the namespace bindings together with the facet value here and resolve it as soon as + * we have all type information available. + */ + void addEnumerationFacetValue(const AtomicValue::Ptr &facetValue, const NamespaceSupport &namespaceSupport); + + /** + * Add a check job for redefined groups. + * + * When an element group is redefined, we have to check whether the redefined group is a valid + * restriction of the group it redefines. As we need all type information for that, we keep them + * here for later checking. + */ + void addRedefinedGroups(const XsdModelGroup::Ptr &redefinedGroup, const XsdModelGroup::Ptr &group); + + /** + * Add a check job for redefined attribute groups. + * + * When an attribute group is redefined, we have to check whether the redefined group is a valid + * restriction of the group it redefines. As we need all type information for that, we keep them + * here for later checking. + */ + void addRedefinedAttributeGroups(const XsdAttributeGroup::Ptr &redefinedGroup, const XsdAttributeGroup::Ptr &group); + + /** + * Adds a check for nested all groups. + */ + void addAllGroupCheck(const XsdReference::Ptr &reference); + + /** + * Copies the data to resolve to an @p other resolver. + * + * @note That functionality is only used by the redefine algorithm in the XsdSchemaParser. + */ + void copyDataTo(const XsdSchemaResolver::Ptr &other) const; + + /** + * Returns the to resolve base type name for the given @p type. + * + * @note That functionality is only used by the redefine algorithm in the XsdSchemaParser. + */ + QXmlName baseTypeNameOfType(const SchemaType::Ptr &type) const; + + /** + * Returns the to resolve type name for the given @p attribute. + * + * @note That functionality is only used by the redefine algorithm in the XsdSchemaParser. + */ + QXmlName typeNameOfAttribute(const XsdAttribute::Ptr &attribute) const; + + /** + * Sets the defaultOpenContent object from the schema parser. + */ + void setDefaultOpenContent(const XsdComplexType::OpenContent::Ptr &openContent, bool appliesToEmpty); + + private: + /** + * Resolves key references. + */ + void resolveKeyReferences(); + + /** + * Resolves the base types of simple types derived by restriction. + */ + void resolveSimpleRestrictionBaseTypes(); + + /** + * Resolves the other properties except the base type + * of all simple restrictions. + */ + void resolveSimpleRestrictions(); + + /** + * Resolves the other properties except the base type + * of the given simple restriction. + * + * @param simpleType The restricted type to resolve. + * @param visitedTypes A set of already resolved types, used for termination of recursion. + */ + void resolveSimpleRestrictions(const XsdSimpleType::Ptr &simpleType, QSet &visitedTypes); + + /** + * Resolves the item type property of simple types derived by list. + */ + void resolveSimpleListType(); + + /** + * Resolves the member types property of simple types derived by union. + */ + void resolveSimpleUnionTypes(); + + /** + * Resolves element types. + */ + void resolveElementTypes(); + + /** + * Resolves base type of complex types. + */ + void resolveComplexBaseTypes(); + + /** + * Resolves the simple content model of a complex type + * depending on its base type. + */ + void resolveSimpleContentComplexTypes(); + + /** + * Resolves the complex content model of a complex type + * depending on its base type. + */ + void resolveComplexContentComplexTypes(); + + /** + * Resolves the simple content model of a complex type + * depending on its base type. + * + * @param complexType The complex type to resolve. + * @param visitedTypes A set of already resolved types, used for termination of recursion. + */ + void resolveSimpleContentComplexTypes(const XsdComplexType::Ptr &complexType, QSet &visitedTypes); + + /** + * Resolves the complex content model of a complex type + * depending on its base type. + * + * @param complexType The complex type to resolve. + * @param visitedTypes A set of already resolved types, used for termination of recursion. + */ + void resolveComplexContentComplexTypes(const XsdComplexType::Ptr &complexType, QSet &visitedTypes); + + /** + * Resolves attribute types. + */ + void resolveAttributeTypes(); + + /** + * Resolves alternative types. + */ + void resolveAlternativeTypes(); + + /** + * Resolves substitution group affiliations. + */ + void resolveSubstitutionGroupAffiliations(); + + /** + * Resolves substitution groups. + */ + void resolveSubstitutionGroups(); + + /** + * Resolves all XsdReferences in the schema by their corresponding XsdElement or XsdModelGroup terms. + */ + void resolveTermReferences(); + + /** + * Resolves all XsdReferences in the @p particle recursive by their corresponding XsdElement or XsdModelGroup terms. + */ + void resolveTermReference(const XsdParticle::Ptr &particle, QSet visitedGroups); + + /** + * Resolves all XsdAttributeReferences in the schema by their corresponding XsdAttributeUse objects. + */ + void resolveAttributeTermReferences(); + + /** + * Resolves all XsdAttributeReferences in the list of @p attributeUses by their corresponding XsdAttributeUse objects. + */ + XsdAttributeUse::List resolveAttributeTermReferences(const XsdAttributeUse::List &attributeUses, XsdWildcard::Ptr &wildcard, QSet visitedAttributeGroups); + + /** + * Resolves the attribute inheritance of complex types. + * + * @note This method must be called after all base types have been resolved. + */ + void resolveAttributeInheritance(); + + /** + * Resolves the attribute inheritance of the given complex types. + * + * @param complexType The complex type to resolve. + * @param visitedTypes A set of already resolved types, used for termination of recursion. + * + * @note This method must be called after all base types have been resolved. + */ + void resolveAttributeInheritance(const XsdComplexType::Ptr &complexType, QSet &visitedTypes); + + /** + * Resolves the enumeration facet values for QName and NOTATION based facets. + */ + void resolveEnumerationFacetValues(); + + /** + * Returns the source location of the given schema @p component or a dummy + * source location if the component is not found in the component location hash. + */ + QSourceLocation sourceLocation(const NamedSchemaComponent::Ptr component) const; + + /** + * Returns the facets that are marked for the given complex @p type with a simple + * type restriction. + */ + XsdFacet::Hash complexTypeFacets(const XsdComplexType::Ptr &complexType) const; + + /** + * Finds the primitive type for the given simple @p type. + * + * The type is found by walking up the inheritance tree, until one of the builtin + * primitive type definitions is reached. + */ + AnySimpleType::Ptr findPrimitiveType(const AnySimpleType::Ptr &type, QSet &visitedTypes); + + /** + * Checks the redefined groups. + */ + void checkRedefinedGroups(); + + /** + * Checks the redefined attribute groups. + */ + void checkRedefinedAttributeGroups(); + + class KeyReference + { + public: + XsdElement::Ptr element; + XsdIdentityConstraint::Ptr keyRef; + QXmlName reference; + QSourceLocation location; + }; + + class SimpleRestrictionBase + { + public: + XsdSimpleType::Ptr simpleType; + QXmlName baseName; + QSourceLocation location; + }; + + class SimpleListType + { + public: + XsdSimpleType::Ptr simpleType; + QXmlName typeName; + QSourceLocation location; + }; + + class SimpleUnionType + { + public: + XsdSimpleType::Ptr simpleType; + QList typeNames; + QSourceLocation location; + }; + + class ElementType + { + public: + XsdElement::Ptr element; + QXmlName typeName; + QSourceLocation location; + }; + + class ComplexBaseType + { + public: + XsdComplexType::Ptr complexType; + QXmlName baseName; + QSourceLocation location; + XsdFacet::Hash facets; + }; + + class ComplexContentType + { + public: + XsdComplexType::Ptr complexType; + XsdParticle::Ptr explicitContent; + bool effectiveMixed; + }; + + class AttributeType + { + public: + XsdAttribute::Ptr attribute; + QXmlName typeName; + QSourceLocation location; + }; + + class AlternativeType + { + public: + XsdAlternative::Ptr alternative; + QXmlName typeName; + QSourceLocation location; + }; + + class AlternativeTypeElement + { + public: + XsdAlternative::Ptr alternative; + XsdElement::Ptr element; + }; + + class SubstitutionGroupAffiliation + { + public: + XsdElement::Ptr element; + QList elementNames; + QSourceLocation location; + }; + + class RedefinedGroups + { + public: + XsdModelGroup::Ptr redefinedGroup; + XsdModelGroup::Ptr group; + }; + + class RedefinedAttributeGroups + { + public: + XsdAttributeGroup::Ptr redefinedGroup; + XsdAttributeGroup::Ptr group; + }; + + QVector m_keyReferences; + QVector m_simpleRestrictionBases; + QVector m_simpleListTypes; + QVector m_simpleUnionTypes; + QVector m_elementTypes; + QVector m_complexBaseTypes; + QVector m_complexContentTypes; + QVector m_attributeTypes; + QVector m_alternativeTypes; + QVector m_alternativeTypeElements; + QVector m_substitutionGroupAffiliations; + QVector m_substitutionGroupTypes; + QVector m_redefinedGroups; + QVector m_redefinedAttributeGroups; + QHash m_enumerationFacetValues; + QSet m_allGroups; + + QExplicitlySharedDataPointer m_context; + QExplicitlySharedDataPointer m_checker; + NamePool::Ptr m_namePool; + XsdSchema::Ptr m_schema; + QHash m_componentLocationHash; + XsdComplexType::OpenContent::Ptr m_defaultOpenContent; + bool m_defaultOpenContentAppliesToEmpty; + SchemaType::List m_predefinedSchemaTypes; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsdschematoken.cpp b/src/xmlpatterns/schema/qxsdschematoken.cpp new file mode 100644 index 0000000..b527de6 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdschematoken.cpp @@ -0,0 +1,2951 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +/* NOTE: This file is AUTO GENERATED by qautomaton2cpp.xsl. */ + +#include "qxsdschematoken_p.h" + +QT_BEGIN_NAMESPACE + +XsdSchemaToken::NodeName XsdSchemaToken::classifier2(const QChar *data) + + { + + static const unsigned short string[] = + { + 105, 100 + }; + if(memcmp(&data[0], &string, sizeof(QChar) * 2) == 0) + + + return Id; + + + return NoKeyword; + } + XsdSchemaToken::NodeName XsdSchemaToken::classifier3(const QChar *data) + + { + if (data[0] == 97) + + + { + if (data[1] == 108) + + + { + + if(data[2] == 108) + + + return All; + + } + + else if (data[1] == 110) + + + { + + if(data[2] == 121) + + + return Any; + + } + + + } + + else if (data[0] == 107) + + + { + + static const unsigned short string[] = + { + 101, 121 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 2) == 0) + + + return Key; + + } + + else if (data[0] == 114) + + + { + + static const unsigned short string[] = + { + 101, 102 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 2) == 0) + + + return Ref; + + } + + else if (data[0] == 117) + + + { + + static const unsigned short string[] = + { + 115, 101 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 2) == 0) + + + return Use; + + } + + + + return NoKeyword; + } + XsdSchemaToken::NodeName XsdSchemaToken::classifier4(const QChar *data) + + { + if (data[0] == 98) + + + { + + static const unsigned short string[] = + { + 97, 115, 101 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 3) == 0) + + + return Base; + + } + + else if (data[0] == 102) + + + { + + static const unsigned short string[] = + { + 111, 114, 109 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 3) == 0) + + + return Form; + + } + + else if (data[0] == 108) + + + { + + static const unsigned short string[] = + { + 105, 115, 116 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 3) == 0) + + + return List; + + } + + else if (data[0] == 109) + + + { + + static const unsigned short string[] = + { + 111, 100, 101 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 3) == 0) + + + return Mode; + + } + + else if (data[0] == 110) + + + { + + static const unsigned short string[] = + { + 97, 109, 101 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 3) == 0) + + + return Name; + + } + + else if (data[0] == 116) + + + { + if (data[1] == 101) + + + { + + static const unsigned short string[] = + { + 115, 116 + }; + if(memcmp(&data[2], &string, sizeof(QChar) * 2) == 0) + + + return Test; + + } + + else if (data[1] == 121) + + + { + + static const unsigned short string[] = + { + 112, 101 + }; + if(memcmp(&data[2], &string, sizeof(QChar) * 2) == 0) + + + return Type; + + } + + + } + + + + return NoKeyword; + } + XsdSchemaToken::NodeName XsdSchemaToken::classifier5(const QChar *data) + + { + if (data[0] == 98) + + + { + + static const unsigned short string[] = + { + 108, 111, 99, 107 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 4) == 0) + + + return Block; + + } + + else if (data[0] == 102) + + + { + if (data[1] == 105) + + + { + if (data[2] == 101) + + + { + + static const unsigned short string[] = + { + 108, 100 + }; + if(memcmp(&data[3], &string, sizeof(QChar) * 2) == 0) + + + return Field; + + } + + else if (data[2] == 110) + + + { + + static const unsigned short string[] = + { + 97, 108 + }; + if(memcmp(&data[3], &string, sizeof(QChar) * 2) == 0) + + + return Final; + + } + + else if (data[2] == 120) + + + { + + static const unsigned short string[] = + { + 101, 100 + }; + if(memcmp(&data[3], &string, sizeof(QChar) * 2) == 0) + + + return Fixed; + + } + + + } + + + } + + else if (data[0] == 103) + + + { + + static const unsigned short string[] = + { + 114, 111, 117, 112 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 4) == 0) + + + return Group; + + } + + else if (data[0] == 109) + + + { + + static const unsigned short string[] = + { + 105, 120, 101, 100 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 4) == 0) + + + return Mixed; + + } + + else if (data[0] == 114) + + + { + + static const unsigned short string[] = + { + 101, 102, 101, 114 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 4) == 0) + + + return Refer; + + } + + else if (data[0] == 117) + + + { + + static const unsigned short string[] = + { + 110, 105, 111, 110 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 4) == 0) + + + return Union; + + } + + else if (data[0] == 118) + + + { + + static const unsigned short string[] = + { + 97, 108, 117, 101 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 4) == 0) + + + return Value; + + } + + else if (data[0] == 120) + + + { + + static const unsigned short string[] = + { + 112, 97, 116, 104 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 4) == 0) + + + return Xpath; + + } + + + + return NoKeyword; + } + XsdSchemaToken::NodeName XsdSchemaToken::classifier6(const QChar *data) + + { + if (data[0] == 97) + + + { + + static const unsigned short string[] = + { + 115, 115, 101, 114, 116 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 5) == 0) + + + return Assert; + + } + + else if (data[0] == 99) + + + { + + static const unsigned short string[] = + { + 104, 111, 105, 99, 101 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 5) == 0) + + + return Choice; + + } + + else if (data[0] == 105) + + + { + + static const unsigned short string[] = + { + 109, 112, 111, 114, 116 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 5) == 0) + + + return Import; + + } + + else if (data[0] == 107) + + + { + + static const unsigned short string[] = + { + 101, 121, 114, 101, 102 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 5) == 0) + + + return Keyref; + + } + + else if (data[0] == 108) + + + { + + static const unsigned short string[] = + { + 101, 110, 103, 116, 104 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 5) == 0) + + + return Length; + + } + + else if (data[0] == 112) + + + { + + static const unsigned short string[] = + { + 117, 98, 108, 105, 99 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 5) == 0) + + + return Public; + + } + + else if (data[0] == 115) + + + { + if (data[1] == 99) + + + { + + static const unsigned short string[] = + { + 104, 101, 109, 97 + }; + if(memcmp(&data[2], &string, sizeof(QChar) * 4) == 0) + + + return Schema; + + } + + else if (data[1] == 111) + + + { + + static const unsigned short string[] = + { + 117, 114, 99, 101 + }; + if(memcmp(&data[2], &string, sizeof(QChar) * 4) == 0) + + + return Source; + + } + + else if (data[1] == 121) + + + { + + static const unsigned short string[] = + { + 115, 116, 101, 109 + }; + if(memcmp(&data[2], &string, sizeof(QChar) * 4) == 0) + + + return System; + + } + + + } + + else if (data[0] == 117) + + + { + + static const unsigned short string[] = + { + 110, 105, 113, 117, 101 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 5) == 0) + + + return Unique; + + } + + + + return NoKeyword; + } + XsdSchemaToken::NodeName XsdSchemaToken::classifier7(const QChar *data) + + { + if (data[0] == 97) + + + { + + static const unsigned short string[] = + { + 112, 112, 105, 110, 102, 111 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 6) == 0) + + + return Appinfo; + + } + + else if (data[0] == 100) + + + { + + static const unsigned short string[] = + { + 101, 102, 97, 117, 108, 116 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 6) == 0) + + + return Default; + + } + + else if (data[0] == 101) + + + { + + static const unsigned short string[] = + { + 108, 101, 109, 101, 110, 116 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 6) == 0) + + + return Element; + + } + + else if (data[0] == 105) + + + { + + static const unsigned short string[] = + { + 110, 99, 108, 117, 100, 101 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 6) == 0) + + + return Include; + + } + + else if (data[0] == 112) + + + { + + static const unsigned short string[] = + { + 97, 116, 116, 101, 114, 110 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 6) == 0) + + + return Pattern; + + } + + else if (data[0] == 114) + + + { + + static const unsigned short string[] = + { + 101, 112, 108, 97, 99, 101 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 6) == 0) + + + return Replace; + + } + + else if (data[0] == 118) + + + { + + static const unsigned short string[] = + { + 101, 114, 115, 105, 111, 110 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 6) == 0) + + + return Version; + + } + + + + return NoKeyword; + } + XsdSchemaToken::NodeName XsdSchemaToken::classifier8(const QChar *data) + + { + if (data[0] == 97) + + + { + + static const unsigned short string[] = + { + 98, 115, 116, 114, 97, 99, 116 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 7) == 0) + + + return Abstract; + + } + + else if (data[0] == 99) + + + { + + static const unsigned short string[] = + { + 111, 108, 108, 97, 112, 115, 101 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 7) == 0) + + + return Collapse; + + } + + else if (data[0] == 105) + + + { + + static const unsigned short string[] = + { + 116, 101, 109, 84, 121, 112, 101 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 7) == 0) + + + return ItemType; + + } + + else if (data[0] == 110) + + + { + if (data[1] == 105) + + + { + + static const unsigned short string[] = + { + 108, 108, 97, 98, 108, 101 + }; + if(memcmp(&data[2], &string, sizeof(QChar) * 6) == 0) + + + return Nillable; + + } + + else if (data[1] == 111) + + + { + if (data[2] == 116) + + + { + if (data[3] == 97) + + + { + + static const unsigned short string[] = + { + 116, 105, 111, 110 + }; + if(memcmp(&data[4], &string, sizeof(QChar) * 4) == 0) + + + return Notation; + + } + + else if (data[3] == 81) + + + { + + static const unsigned short string[] = + { + 78, 97, 109, 101 + }; + if(memcmp(&data[4], &string, sizeof(QChar) * 4) == 0) + + + return NotQName; + + } + + + } + + + } + + + } + + else if (data[0] == 111) + + + { + + static const unsigned short string[] = + { + 118, 101, 114, 114, 105, 100, 101 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 7) == 0) + + + return Override; + + } + + else if (data[0] == 112) + + + { + + static const unsigned short string[] = + { + 114, 101, 115, 101, 114, 118, 101 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 7) == 0) + + + return Preserve; + + } + + else if (data[0] == 114) + + + { + + static const unsigned short string[] = + { + 101, 100, 101, 102, 105, 110, 101 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 7) == 0) + + + return Redefine; + + } + + else if (data[0] == 115) + + + { + if (data[1] == 101) + + + { + if (data[2] == 108) + + + { + + static const unsigned short string[] = + { + 101, 99, 116, 111, 114 + }; + if(memcmp(&data[3], &string, sizeof(QChar) * 5) == 0) + + + return Selector; + + } + + else if (data[2] == 113) + + + { + + static const unsigned short string[] = + { + 117, 101, 110, 99, 101 + }; + if(memcmp(&data[3], &string, sizeof(QChar) * 5) == 0) + + + return Sequence; + + } + + + } + + + } + + else if (data[0] == 120) + + + { + + static const unsigned short string[] = + { + 109, 108, 58, 108, 97, 110, 103 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 7) == 0) + + + return XmlLanguage; + + } + + + + return NoKeyword; + } + XsdSchemaToken::NodeName XsdSchemaToken::classifier9(const QChar *data) + + { + if (data[0] == 97) + + + { + if (data[1] == 115) + + + { + + static const unsigned short string[] = + { + 115, 101, 114, 116, 105, 111, 110 + }; + if(memcmp(&data[2], &string, sizeof(QChar) * 7) == 0) + + + return Assertion; + + } + + else if (data[1] == 116) + + + { + + static const unsigned short string[] = + { + 116, 114, 105, 98, 117, 116, 101 + }; + if(memcmp(&data[2], &string, sizeof(QChar) * 7) == 0) + + + return Attribute; + + } + + + } + + else if (data[0] == 101) + + + { + + static const unsigned short string[] = + { + 120, 116, 101, 110, 115, 105, 111, 110 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 8) == 0) + + + return Extension; + + } + + else if (data[0] == 109) + + + { + if (data[1] == 97) + + + { + if (data[2] == 120) + + + { + if (data[3] == 76) + + + { + + static const unsigned short string[] = + { + 101, 110, 103, 116, 104 + }; + if(memcmp(&data[4], &string, sizeof(QChar) * 5) == 0) + + + return MaxLength; + + } + + else if (data[3] == 79) + + + { + + static const unsigned short string[] = + { + 99, 99, 117, 114, 115 + }; + if(memcmp(&data[4], &string, sizeof(QChar) * 5) == 0) + + + return MaxOccurs; + + } + + + } + + + } + + else if (data[1] == 105) + + + { + if (data[2] == 110) + + + { + if (data[3] == 76) + + + { + + static const unsigned short string[] = + { + 101, 110, 103, 116, 104 + }; + if(memcmp(&data[4], &string, sizeof(QChar) * 5) == 0) + + + return MinLength; + + } + + else if (data[3] == 79) + + + { + + static const unsigned short string[] = + { + 99, 99, 117, 114, 115 + }; + if(memcmp(&data[4], &string, sizeof(QChar) * 5) == 0) + + + return MinOccurs; + + } + + + } + + + } + + + } + + else if (data[0] == 110) + + + { + + static const unsigned short string[] = + { + 97, 109, 101, 115, 112, 97, 99, 101 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 8) == 0) + + + return Namespace; + + } + + + + return NoKeyword; + } + XsdSchemaToken::NodeName XsdSchemaToken::classifier10(const QChar *data) + + { + if (data[0] == 97) + + + { + + static const unsigned short string[] = + { + 110, 110, 111, 116, 97, 116, 105, 111, 110 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 9) == 0) + + + return Annotation; + + } + + else if (data[0] == 115) + + + { + + static const unsigned short string[] = + { + 105, 109, 112, 108, 101, 84, 121, 112, 101 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 9) == 0) + + + return SimpleType; + + } + + else if (data[0] == 119) + + + { + + static const unsigned short string[] = + { + 104, 105, 116, 101, 83, 112, 97, 99, 101 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 9) == 0) + + + return WhiteSpace; + + } + + + + return NoKeyword; + } + XsdSchemaToken::NodeName XsdSchemaToken::classifier11(const QChar *data) + + { + if (data[0] == 97) + + + { + + static const unsigned short string[] = + { + 108, 116, 101, 114, 110, 97, 116, 105, 118, 101 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 10) == 0) + + + return Alternative; + + } + + else if (data[0] == 99) + + + { + + static const unsigned short string[] = + { + 111, 109, 112, 108, 101, 120, 84, 121, 112, 101 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 10) == 0) + + + return ComplexType; + + } + + else if (data[0] == 101) + + + { + + static const unsigned short string[] = + { + 110, 117, 109, 101, 114, 97, 116, 105, 111, 110 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 10) == 0) + + + return Enumeration; + + } + + else if (data[0] == 109) + + + { + + static const unsigned short string[] = + { + 101, 109, 98, 101, 114, 84, 121, 112, 101, 115 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 10) == 0) + + + return MemberTypes; + + } + + else if (data[0] == 111) + + + { + + static const unsigned short string[] = + { + 112, 101, 110, 67, 111, 110, 116, 101, 110, 116 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 10) == 0) + + + return OpenContent; + + } + + else if (data[0] == 114) + + + { + + static const unsigned short string[] = + { + 101, 115, 116, 114, 105, 99, 116, 105, 111, 110 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 10) == 0) + + + return Restriction; + + } + + else if (data[0] == 116) + + + { + + static const unsigned short string[] = + { + 111, 116, 97, 108, 68, 105, 103, 105, 116, 115 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 10) == 0) + + + return TotalDigits; + + } + + + + return NoKeyword; + } + XsdSchemaToken::NodeName XsdSchemaToken::classifier12(const QChar *data) + + { + if (data[0] == 97) + + + { + + static const unsigned short string[] = + { + 110, 121, 65, 116, 116, 114, 105, 98, 117, 116, 101 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 11) == 0) + + + return AnyAttribute; + + } + + else if (data[0] == 98) + + + { + + static const unsigned short string[] = + { + 108, 111, 99, 107, 68, 101, 102, 97, 117, 108, 116 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 11) == 0) + + + return BlockDefault; + + } + + else if (data[0] == 102) + + + { + + static const unsigned short string[] = + { + 105, 110, 97, 108, 68, 101, 102, 97, 117, 108, 116 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 11) == 0) + + + return FinalDefault; + + } + + else if (data[0] == 109) + + + { + if (data[1] == 97) + + + { + if (data[2] == 120) + + + { + if (data[3] == 69) + + + { + + static const unsigned short string[] = + { + 120, 99, 108, 117, 115, 105, 118, 101 + }; + if(memcmp(&data[4], &string, sizeof(QChar) * 8) == 0) + + + return MaxExclusive; + + } + + else if (data[3] == 73) + + + { + + static const unsigned short string[] = + { + 110, 99, 108, 117, 115, 105, 118, 101 + }; + if(memcmp(&data[4], &string, sizeof(QChar) * 8) == 0) + + + return MaxInclusive; + + } + + + } + + + } + + else if (data[1] == 105) + + + { + if (data[2] == 110) + + + { + if (data[3] == 69) + + + { + + static const unsigned short string[] = + { + 120, 99, 108, 117, 115, 105, 118, 101 + }; + if(memcmp(&data[4], &string, sizeof(QChar) * 8) == 0) + + + return MinExclusive; + + } + + else if (data[3] == 73) + + + { + + static const unsigned short string[] = + { + 110, 99, 108, 117, 115, 105, 118, 101 + }; + if(memcmp(&data[4], &string, sizeof(QChar) * 8) == 0) + + + return MinInclusive; + + } + + + } + + + } + + + } + + else if (data[0] == 110) + + + { + + static const unsigned short string[] = + { + 111, 116, 78, 97, 109, 101, 115, 112, 97, 99, 101 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 11) == 0) + + + return NotNamespace; + + } + + + + return NoKeyword; + } + XsdSchemaToken::NodeName XsdSchemaToken::classifier13(const QChar *data) + + { + if (data[0] == 100) + + + { + + static const unsigned short string[] = + { + 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 12) == 0) + + + return Documentation; + + } + + else if (data[0] == 115) + + + { + + static const unsigned short string[] = + { + 105, 109, 112, 108, 101, 67, 111, 110, 116, 101, 110, 116 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 12) == 0) + + + return SimpleContent; + + } + + + + return NoKeyword; + } + XsdSchemaToken::NodeName XsdSchemaToken::classifier14(const QChar *data) + + { + if (data[0] == 97) + + + { + if (data[1] == 112) + + + { + + static const unsigned short string[] = + { + 112, 108, 105, 101, 115, 84, 111, 69, 109, 112, 116, 121 + }; + if(memcmp(&data[2], &string, sizeof(QChar) * 12) == 0) + + + return AppliesToEmpty; + + } + + else if (data[1] == 116) + + + { + + static const unsigned short string[] = + { + 116, 114, 105, 98, 117, 116, 101, 71, 114, 111, 117, 112 + }; + if(memcmp(&data[2], &string, sizeof(QChar) * 12) == 0) + + + return AttributeGroup; + + } + + + } + + else if (data[0] == 99) + + + { + + static const unsigned short string[] = + { + 111, 109, 112, 108, 101, 120, 67, 111, 110, 116, 101, 110, 116 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 13) == 0) + + + return ComplexContent; + + } + + else if (data[0] == 102) + + + { + + static const unsigned short string[] = + { + 114, 97, 99, 116, 105, 111, 110, 68, 105, 103, 105, 116, 115 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 13) == 0) + + + return FractionDigits; + + } + + else if (data[0] == 115) + + + { + + static const unsigned short string[] = + { + 99, 104, 101, 109, 97, 76, 111, 99, 97, 116, 105, 111, 110 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 13) == 0) + + + return SchemaLocation; + + } + + + + return NoKeyword; + } + XsdSchemaToken::NodeName XsdSchemaToken::classifier15(const QChar *data) + + { + if (data[0] == 112) + + + { + + static const unsigned short string[] = + { + 114, 111, 99, 101, 115, 115, 67, 111, 110, 116, 101, 110, 116, 115 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 14) == 0) + + + return ProcessContents; + + } + + else if (data[0] == 116) + + + { + + static const unsigned short string[] = + { + 97, 114, 103, 101, 116, 78, 97, 109, 101, 115, 112, 97, 99, 101 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 14) == 0) + + + return TargetNamespace; + + } + + + + return NoKeyword; + } + XsdSchemaToken::NodeName XsdSchemaToken::classifier17(const QChar *data) + + { + if (data[0] == 100) + + + { + + static const unsigned short string[] = + { + 101, 102, 97, 117, 108, 116, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 16) == 0) + + + return DefaultAttributes; + + } + + else if (data[0] == 115) + + + { + + static const unsigned short string[] = + { + 117, 98, 115, 116, 105, 116, 117, 116, 105, 111, 110, 71, 114, 111, 117, 112 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 16) == 0) + + + return SubstitutionGroup; + + } + + + + return NoKeyword; + } + XsdSchemaToken::NodeName XsdSchemaToken::classifier18(const QChar *data) + + { + if (data[0] == 100) + + + { + + static const unsigned short string[] = + { + 101, 102, 97, 117, 108, 116, 79, 112, 101, 110, 67, 111, 110, 116, 101, 110, 116 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 17) == 0) + + + return DefaultOpenContent; + + } + + else if (data[0] == 101) + + + { + + static const unsigned short string[] = + { + 108, 101, 109, 101, 110, 116, 70, 111, 114, 109, 68, 101, 102, 97, 117, 108, 116 + }; + if(memcmp(&data[1], &string, sizeof(QChar) * 17) == 0) + + + return ElementFormDefault; + + } + + + + return NoKeyword; + } + XsdSchemaToken::NodeName XsdSchemaToken::classifier20(const QChar *data) + + { + + static const unsigned short string[] = + { + 97, 116, 116, 114, 105, 98, 117, 116, 101, 70, 111, 114, 109, 68, 101, 102, 97, 117, 108, 116 + }; + if(memcmp(&data[0], &string, sizeof(QChar) * 20) == 0) + + + return AttributeFormDefault; + + + return NoKeyword; + } + XsdSchemaToken::NodeName XsdSchemaToken::classifier21(const QChar *data) + + { + + static const unsigned short string[] = + { + 120, 112, 97, 116, 104, 68, 101, 102, 97, 117, 108, 116, 78, 97, 109, 101, 115, 112, 97, 99, 101 + }; + if(memcmp(&data[0], &string, sizeof(QChar) * 21) == 0) + + + return XPathDefaultNamespace; + + + return NoKeyword; + } + XsdSchemaToken::NodeName XsdSchemaToken::classifier22(const QChar *data) + + { + + static const unsigned short string[] = + { + 100, 101, 102, 97, 117, 108, 116, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 65, 112, 112, 108, 121 + }; + if(memcmp(&data[0], &string, sizeof(QChar) * 22) == 0) + + + return DefaultAttributesApply; + + + return NoKeyword; + } + XsdSchemaToken::NodeName XsdSchemaToken::classifier32(const QChar *data) + + { + + static const unsigned short string[] = + { + 104, 116, 116, 112, 58, 47, 47, 119, 119, 119, 46, 119, 51, 46, 111, 114, 103, 47, 50, 48, 48, 49, 47, 88, 77, 76, 83, 99, 104, 101, 109, 97 + }; + if(memcmp(&data[0], &string, sizeof(QChar) * 32) == 0) + + + return XML_NS_SCHEMA_URI; + + + return NoKeyword; + } + XsdSchemaToken::NodeName XsdSchemaToken::toToken(const QChar *data, int length) + { + switch(length) + { + + case 2: + return classifier2(data); + + + case 3: + return classifier3(data); + + + case 4: + return classifier4(data); + + + case 5: + return classifier5(data); + + + case 6: + return classifier6(data); + + + case 7: + return classifier7(data); + + + case 8: + return classifier8(data); + + + case 9: + return classifier9(data); + + + case 10: + return classifier10(data); + + + case 11: + return classifier11(data); + + + case 12: + return classifier12(data); + + + case 13: + return classifier13(data); + + + case 14: + return classifier14(data); + + + case 15: + return classifier15(data); + + + case 17: + return classifier17(data); + + + case 18: + return classifier18(data); + + + case 20: + return classifier20(data); + + + case 21: + return classifier21(data); + + + case 22: + return classifier22(data); + + + case 32: + return classifier32(data); + + + default: + return NoKeyword; + } + } + + + QString XsdSchemaToken::toString(NodeName token) + { + const unsigned short *data = 0; + int length = 0; + + switch(token) + { + + case Abstract: + { + static const unsigned short staticallyStoredAbstract[] = + { + 97, 98, 115, 116, 114, 97, 99, 116, 0 + }; + data = staticallyStoredAbstract; + length = 8; + break; + } + + case All: + { + static const unsigned short staticallyStoredAll[] = + { + 97, 108, 108, 0 + }; + data = staticallyStoredAll; + length = 3; + break; + } + + case Alternative: + { + static const unsigned short staticallyStoredAlternative[] = + { + 97, 108, 116, 101, 114, 110, 97, 116, 105, 118, 101, 0 + }; + data = staticallyStoredAlternative; + length = 11; + break; + } + + case Annotation: + { + static const unsigned short staticallyStoredAnnotation[] = + { + 97, 110, 110, 111, 116, 97, 116, 105, 111, 110, 0 + }; + data = staticallyStoredAnnotation; + length = 10; + break; + } + + case Any: + { + static const unsigned short staticallyStoredAny[] = + { + 97, 110, 121, 0 + }; + data = staticallyStoredAny; + length = 3; + break; + } + + case AnyAttribute: + { + static const unsigned short staticallyStoredAnyAttribute[] = + { + 97, 110, 121, 65, 116, 116, 114, 105, 98, 117, 116, 101, 0 + }; + data = staticallyStoredAnyAttribute; + length = 12; + break; + } + + case Appinfo: + { + static const unsigned short staticallyStoredAppinfo[] = + { + 97, 112, 112, 105, 110, 102, 111, 0 + }; + data = staticallyStoredAppinfo; + length = 7; + break; + } + + case AppliesToEmpty: + { + static const unsigned short staticallyStoredAppliesToEmpty[] = + { + 97, 112, 112, 108, 105, 101, 115, 84, 111, 69, 109, 112, 116, 121, 0 + }; + data = staticallyStoredAppliesToEmpty; + length = 14; + break; + } + + case Assert: + { + static const unsigned short staticallyStoredAssert[] = + { + 97, 115, 115, 101, 114, 116, 0 + }; + data = staticallyStoredAssert; + length = 6; + break; + } + + case Assertion: + { + static const unsigned short staticallyStoredAssertion[] = + { + 97, 115, 115, 101, 114, 116, 105, 111, 110, 0 + }; + data = staticallyStoredAssertion; + length = 9; + break; + } + + case Attribute: + { + static const unsigned short staticallyStoredAttribute[] = + { + 97, 116, 116, 114, 105, 98, 117, 116, 101, 0 + }; + data = staticallyStoredAttribute; + length = 9; + break; + } + + case AttributeFormDefault: + { + static const unsigned short staticallyStoredAttributeFormDefault[] = + { + 97, 116, 116, 114, 105, 98, 117, 116, 101, 70, 111, 114, 109, 68, 101, 102, 97, 117, 108, 116, 0 + }; + data = staticallyStoredAttributeFormDefault; + length = 20; + break; + } + + case AttributeGroup: + { + static const unsigned short staticallyStoredAttributeGroup[] = + { + 97, 116, 116, 114, 105, 98, 117, 116, 101, 71, 114, 111, 117, 112, 0 + }; + data = staticallyStoredAttributeGroup; + length = 14; + break; + } + + case Base: + { + static const unsigned short staticallyStoredBase[] = + { + 98, 97, 115, 101, 0 + }; + data = staticallyStoredBase; + length = 4; + break; + } + + case Block: + { + static const unsigned short staticallyStoredBlock[] = + { + 98, 108, 111, 99, 107, 0 + }; + data = staticallyStoredBlock; + length = 5; + break; + } + + case BlockDefault: + { + static const unsigned short staticallyStoredBlockDefault[] = + { + 98, 108, 111, 99, 107, 68, 101, 102, 97, 117, 108, 116, 0 + }; + data = staticallyStoredBlockDefault; + length = 12; + break; + } + + case Choice: + { + static const unsigned short staticallyStoredChoice[] = + { + 99, 104, 111, 105, 99, 101, 0 + }; + data = staticallyStoredChoice; + length = 6; + break; + } + + case Collapse: + { + static const unsigned short staticallyStoredCollapse[] = + { + 99, 111, 108, 108, 97, 112, 115, 101, 0 + }; + data = staticallyStoredCollapse; + length = 8; + break; + } + + case ComplexContent: + { + static const unsigned short staticallyStoredComplexContent[] = + { + 99, 111, 109, 112, 108, 101, 120, 67, 111, 110, 116, 101, 110, 116, 0 + }; + data = staticallyStoredComplexContent; + length = 14; + break; + } + + case ComplexType: + { + static const unsigned short staticallyStoredComplexType[] = + { + 99, 111, 109, 112, 108, 101, 120, 84, 121, 112, 101, 0 + }; + data = staticallyStoredComplexType; + length = 11; + break; + } + + case Default: + { + static const unsigned short staticallyStoredDefault[] = + { + 100, 101, 102, 97, 117, 108, 116, 0 + }; + data = staticallyStoredDefault; + length = 7; + break; + } + + case DefaultAttributes: + { + static const unsigned short staticallyStoredDefaultAttributes[] = + { + 100, 101, 102, 97, 117, 108, 116, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 0 + }; + data = staticallyStoredDefaultAttributes; + length = 17; + break; + } + + case DefaultAttributesApply: + { + static const unsigned short staticallyStoredDefaultAttributesApply[] = + { + 100, 101, 102, 97, 117, 108, 116, 65, 116, 116, 114, 105, 98, 117, 116, 101, 115, 65, 112, 112, 108, 121, 0 + }; + data = staticallyStoredDefaultAttributesApply; + length = 22; + break; + } + + case DefaultOpenContent: + { + static const unsigned short staticallyStoredDefaultOpenContent[] = + { + 100, 101, 102, 97, 117, 108, 116, 79, 112, 101, 110, 67, 111, 110, 116, 101, 110, 116, 0 + }; + data = staticallyStoredDefaultOpenContent; + length = 18; + break; + } + + case Documentation: + { + static const unsigned short staticallyStoredDocumentation[] = + { + 100, 111, 99, 117, 109, 101, 110, 116, 97, 116, 105, 111, 110, 0 + }; + data = staticallyStoredDocumentation; + length = 13; + break; + } + + case Element: + { + static const unsigned short staticallyStoredElement[] = + { + 101, 108, 101, 109, 101, 110, 116, 0 + }; + data = staticallyStoredElement; + length = 7; + break; + } + + case ElementFormDefault: + { + static const unsigned short staticallyStoredElementFormDefault[] = + { + 101, 108, 101, 109, 101, 110, 116, 70, 111, 114, 109, 68, 101, 102, 97, 117, 108, 116, 0 + }; + data = staticallyStoredElementFormDefault; + length = 18; + break; + } + + case Enumeration: + { + static const unsigned short staticallyStoredEnumeration[] = + { + 101, 110, 117, 109, 101, 114, 97, 116, 105, 111, 110, 0 + }; + data = staticallyStoredEnumeration; + length = 11; + break; + } + + case Extension: + { + static const unsigned short staticallyStoredExtension[] = + { + 101, 120, 116, 101, 110, 115, 105, 111, 110, 0 + }; + data = staticallyStoredExtension; + length = 9; + break; + } + + case Field: + { + static const unsigned short staticallyStoredField[] = + { + 102, 105, 101, 108, 100, 0 + }; + data = staticallyStoredField; + length = 5; + break; + } + + case Final: + { + static const unsigned short staticallyStoredFinal[] = + { + 102, 105, 110, 97, 108, 0 + }; + data = staticallyStoredFinal; + length = 5; + break; + } + + case FinalDefault: + { + static const unsigned short staticallyStoredFinalDefault[] = + { + 102, 105, 110, 97, 108, 68, 101, 102, 97, 117, 108, 116, 0 + }; + data = staticallyStoredFinalDefault; + length = 12; + break; + } + + case Fixed: + { + static const unsigned short staticallyStoredFixed[] = + { + 102, 105, 120, 101, 100, 0 + }; + data = staticallyStoredFixed; + length = 5; + break; + } + + case Form: + { + static const unsigned short staticallyStoredForm[] = + { + 102, 111, 114, 109, 0 + }; + data = staticallyStoredForm; + length = 4; + break; + } + + case FractionDigits: + { + static const unsigned short staticallyStoredFractionDigits[] = + { + 102, 114, 97, 99, 116, 105, 111, 110, 68, 105, 103, 105, 116, 115, 0 + }; + data = staticallyStoredFractionDigits; + length = 14; + break; + } + + case Group: + { + static const unsigned short staticallyStoredGroup[] = + { + 103, 114, 111, 117, 112, 0 + }; + data = staticallyStoredGroup; + length = 5; + break; + } + + case Id: + { + static const unsigned short staticallyStoredId[] = + { + 105, 100, 0 + }; + data = staticallyStoredId; + length = 2; + break; + } + + case Import: + { + static const unsigned short staticallyStoredImport[] = + { + 105, 109, 112, 111, 114, 116, 0 + }; + data = staticallyStoredImport; + length = 6; + break; + } + + case Include: + { + static const unsigned short staticallyStoredInclude[] = + { + 105, 110, 99, 108, 117, 100, 101, 0 + }; + data = staticallyStoredInclude; + length = 7; + break; + } + + case ItemType: + { + static const unsigned short staticallyStoredItemType[] = + { + 105, 116, 101, 109, 84, 121, 112, 101, 0 + }; + data = staticallyStoredItemType; + length = 8; + break; + } + + case Key: + { + static const unsigned short staticallyStoredKey[] = + { + 107, 101, 121, 0 + }; + data = staticallyStoredKey; + length = 3; + break; + } + + case Keyref: + { + static const unsigned short staticallyStoredKeyref[] = + { + 107, 101, 121, 114, 101, 102, 0 + }; + data = staticallyStoredKeyref; + length = 6; + break; + } + + case Length: + { + static const unsigned short staticallyStoredLength[] = + { + 108, 101, 110, 103, 116, 104, 0 + }; + data = staticallyStoredLength; + length = 6; + break; + } + + case List: + { + static const unsigned short staticallyStoredList[] = + { + 108, 105, 115, 116, 0 + }; + data = staticallyStoredList; + length = 4; + break; + } + + case MaxExclusive: + { + static const unsigned short staticallyStoredMaxExclusive[] = + { + 109, 97, 120, 69, 120, 99, 108, 117, 115, 105, 118, 101, 0 + }; + data = staticallyStoredMaxExclusive; + length = 12; + break; + } + + case MaxInclusive: + { + static const unsigned short staticallyStoredMaxInclusive[] = + { + 109, 97, 120, 73, 110, 99, 108, 117, 115, 105, 118, 101, 0 + }; + data = staticallyStoredMaxInclusive; + length = 12; + break; + } + + case MaxLength: + { + static const unsigned short staticallyStoredMaxLength[] = + { + 109, 97, 120, 76, 101, 110, 103, 116, 104, 0 + }; + data = staticallyStoredMaxLength; + length = 9; + break; + } + + case MaxOccurs: + { + static const unsigned short staticallyStoredMaxOccurs[] = + { + 109, 97, 120, 79, 99, 99, 117, 114, 115, 0 + }; + data = staticallyStoredMaxOccurs; + length = 9; + break; + } + + case MemberTypes: + { + static const unsigned short staticallyStoredMemberTypes[] = + { + 109, 101, 109, 98, 101, 114, 84, 121, 112, 101, 115, 0 + }; + data = staticallyStoredMemberTypes; + length = 11; + break; + } + + case MinExclusive: + { + static const unsigned short staticallyStoredMinExclusive[] = + { + 109, 105, 110, 69, 120, 99, 108, 117, 115, 105, 118, 101, 0 + }; + data = staticallyStoredMinExclusive; + length = 12; + break; + } + + case MinInclusive: + { + static const unsigned short staticallyStoredMinInclusive[] = + { + 109, 105, 110, 73, 110, 99, 108, 117, 115, 105, 118, 101, 0 + }; + data = staticallyStoredMinInclusive; + length = 12; + break; + } + + case MinLength: + { + static const unsigned short staticallyStoredMinLength[] = + { + 109, 105, 110, 76, 101, 110, 103, 116, 104, 0 + }; + data = staticallyStoredMinLength; + length = 9; + break; + } + + case MinOccurs: + { + static const unsigned short staticallyStoredMinOccurs[] = + { + 109, 105, 110, 79, 99, 99, 117, 114, 115, 0 + }; + data = staticallyStoredMinOccurs; + length = 9; + break; + } + + case Mixed: + { + static const unsigned short staticallyStoredMixed[] = + { + 109, 105, 120, 101, 100, 0 + }; + data = staticallyStoredMixed; + length = 5; + break; + } + + case Mode: + { + static const unsigned short staticallyStoredMode[] = + { + 109, 111, 100, 101, 0 + }; + data = staticallyStoredMode; + length = 4; + break; + } + + case Name: + { + static const unsigned short staticallyStoredName[] = + { + 110, 97, 109, 101, 0 + }; + data = staticallyStoredName; + length = 4; + break; + } + + case Namespace: + { + static const unsigned short staticallyStoredNamespace[] = + { + 110, 97, 109, 101, 115, 112, 97, 99, 101, 0 + }; + data = staticallyStoredNamespace; + length = 9; + break; + } + + case Nillable: + { + static const unsigned short staticallyStoredNillable[] = + { + 110, 105, 108, 108, 97, 98, 108, 101, 0 + }; + data = staticallyStoredNillable; + length = 8; + break; + } + + case NotNamespace: + { + static const unsigned short staticallyStoredNotNamespace[] = + { + 110, 111, 116, 78, 97, 109, 101, 115, 112, 97, 99, 101, 0 + }; + data = staticallyStoredNotNamespace; + length = 12; + break; + } + + case NotQName: + { + static const unsigned short staticallyStoredNotQName[] = + { + 110, 111, 116, 81, 78, 97, 109, 101, 0 + }; + data = staticallyStoredNotQName; + length = 8; + break; + } + + case Notation: + { + static const unsigned short staticallyStoredNotation[] = + { + 110, 111, 116, 97, 116, 105, 111, 110, 0 + }; + data = staticallyStoredNotation; + length = 8; + break; + } + + case OpenContent: + { + static const unsigned short staticallyStoredOpenContent[] = + { + 111, 112, 101, 110, 67, 111, 110, 116, 101, 110, 116, 0 + }; + data = staticallyStoredOpenContent; + length = 11; + break; + } + + case Override: + { + static const unsigned short staticallyStoredOverride[] = + { + 111, 118, 101, 114, 114, 105, 100, 101, 0 + }; + data = staticallyStoredOverride; + length = 8; + break; + } + + case Pattern: + { + static const unsigned short staticallyStoredPattern[] = + { + 112, 97, 116, 116, 101, 114, 110, 0 + }; + data = staticallyStoredPattern; + length = 7; + break; + } + + case Preserve: + { + static const unsigned short staticallyStoredPreserve[] = + { + 112, 114, 101, 115, 101, 114, 118, 101, 0 + }; + data = staticallyStoredPreserve; + length = 8; + break; + } + + case ProcessContents: + { + static const unsigned short staticallyStoredProcessContents[] = + { + 112, 114, 111, 99, 101, 115, 115, 67, 111, 110, 116, 101, 110, 116, 115, 0 + }; + data = staticallyStoredProcessContents; + length = 15; + break; + } + + case Public: + { + static const unsigned short staticallyStoredPublic[] = + { + 112, 117, 98, 108, 105, 99, 0 + }; + data = staticallyStoredPublic; + length = 6; + break; + } + + case Redefine: + { + static const unsigned short staticallyStoredRedefine[] = + { + 114, 101, 100, 101, 102, 105, 110, 101, 0 + }; + data = staticallyStoredRedefine; + length = 8; + break; + } + + case Ref: + { + static const unsigned short staticallyStoredRef[] = + { + 114, 101, 102, 0 + }; + data = staticallyStoredRef; + length = 3; + break; + } + + case Refer: + { + static const unsigned short staticallyStoredRefer[] = + { + 114, 101, 102, 101, 114, 0 + }; + data = staticallyStoredRefer; + length = 5; + break; + } + + case Replace: + { + static const unsigned short staticallyStoredReplace[] = + { + 114, 101, 112, 108, 97, 99, 101, 0 + }; + data = staticallyStoredReplace; + length = 7; + break; + } + + case Restriction: + { + static const unsigned short staticallyStoredRestriction[] = + { + 114, 101, 115, 116, 114, 105, 99, 116, 105, 111, 110, 0 + }; + data = staticallyStoredRestriction; + length = 11; + break; + } + + case Schema: + { + static const unsigned short staticallyStoredSchema[] = + { + 115, 99, 104, 101, 109, 97, 0 + }; + data = staticallyStoredSchema; + length = 6; + break; + } + + case SchemaLocation: + { + static const unsigned short staticallyStoredSchemaLocation[] = + { + 115, 99, 104, 101, 109, 97, 76, 111, 99, 97, 116, 105, 111, 110, 0 + }; + data = staticallyStoredSchemaLocation; + length = 14; + break; + } + + case Selector: + { + static const unsigned short staticallyStoredSelector[] = + { + 115, 101, 108, 101, 99, 116, 111, 114, 0 + }; + data = staticallyStoredSelector; + length = 8; + break; + } + + case Sequence: + { + static const unsigned short staticallyStoredSequence[] = + { + 115, 101, 113, 117, 101, 110, 99, 101, 0 + }; + data = staticallyStoredSequence; + length = 8; + break; + } + + case SimpleContent: + { + static const unsigned short staticallyStoredSimpleContent[] = + { + 115, 105, 109, 112, 108, 101, 67, 111, 110, 116, 101, 110, 116, 0 + }; + data = staticallyStoredSimpleContent; + length = 13; + break; + } + + case SimpleType: + { + static const unsigned short staticallyStoredSimpleType[] = + { + 115, 105, 109, 112, 108, 101, 84, 121, 112, 101, 0 + }; + data = staticallyStoredSimpleType; + length = 10; + break; + } + + case Source: + { + static const unsigned short staticallyStoredSource[] = + { + 115, 111, 117, 114, 99, 101, 0 + }; + data = staticallyStoredSource; + length = 6; + break; + } + + case SubstitutionGroup: + { + static const unsigned short staticallyStoredSubstitutionGroup[] = + { + 115, 117, 98, 115, 116, 105, 116, 117, 116, 105, 111, 110, 71, 114, 111, 117, 112, 0 + }; + data = staticallyStoredSubstitutionGroup; + length = 17; + break; + } + + case System: + { + static const unsigned short staticallyStoredSystem[] = + { + 115, 121, 115, 116, 101, 109, 0 + }; + data = staticallyStoredSystem; + length = 6; + break; + } + + case TargetNamespace: + { + static const unsigned short staticallyStoredTargetNamespace[] = + { + 116, 97, 114, 103, 101, 116, 78, 97, 109, 101, 115, 112, 97, 99, 101, 0 + }; + data = staticallyStoredTargetNamespace; + length = 15; + break; + } + + case Test: + { + static const unsigned short staticallyStoredTest[] = + { + 116, 101, 115, 116, 0 + }; + data = staticallyStoredTest; + length = 4; + break; + } + + case TotalDigits: + { + static const unsigned short staticallyStoredTotalDigits[] = + { + 116, 111, 116, 97, 108, 68, 105, 103, 105, 116, 115, 0 + }; + data = staticallyStoredTotalDigits; + length = 11; + break; + } + + case Type: + { + static const unsigned short staticallyStoredType[] = + { + 116, 121, 112, 101, 0 + }; + data = staticallyStoredType; + length = 4; + break; + } + + case Union: + { + static const unsigned short staticallyStoredUnion[] = + { + 117, 110, 105, 111, 110, 0 + }; + data = staticallyStoredUnion; + length = 5; + break; + } + + case Unique: + { + static const unsigned short staticallyStoredUnique[] = + { + 117, 110, 105, 113, 117, 101, 0 + }; + data = staticallyStoredUnique; + length = 6; + break; + } + + case Use: + { + static const unsigned short staticallyStoredUse[] = + { + 117, 115, 101, 0 + }; + data = staticallyStoredUse; + length = 3; + break; + } + + case Value: + { + static const unsigned short staticallyStoredValue[] = + { + 118, 97, 108, 117, 101, 0 + }; + data = staticallyStoredValue; + length = 5; + break; + } + + case Version: + { + static const unsigned short staticallyStoredVersion[] = + { + 118, 101, 114, 115, 105, 111, 110, 0 + }; + data = staticallyStoredVersion; + length = 7; + break; + } + + case WhiteSpace: + { + static const unsigned short staticallyStoredWhiteSpace[] = + { + 119, 104, 105, 116, 101, 83, 112, 97, 99, 101, 0 + }; + data = staticallyStoredWhiteSpace; + length = 10; + break; + } + + case XML_NS_SCHEMA_URI: + { + static const unsigned short staticallyStoredXML_NS_SCHEMA_URI[] = + { + 104, 116, 116, 112, 58, 47, 47, 119, 119, 119, 46, 119, 51, 46, 111, 114, 103, 47, 50, 48, 48, 49, 47, 88, 77, 76, 83, 99, 104, 101, 109, 97, 0 + }; + data = staticallyStoredXML_NS_SCHEMA_URI; + length = 32; + break; + } + + case XPathDefaultNamespace: + { + static const unsigned short staticallyStoredXPathDefaultNamespace[] = + { + 120, 112, 97, 116, 104, 68, 101, 102, 97, 117, 108, 116, 78, 97, 109, 101, 115, 112, 97, 99, 101, 0 + }; + data = staticallyStoredXPathDefaultNamespace; + length = 21; + break; + } + + case XmlLanguage: + { + static const unsigned short staticallyStoredXmlLanguage[] = + { + 120, 109, 108, 58, 108, 97, 110, 103, 0 + }; + data = staticallyStoredXmlLanguage; + length = 8; + break; + } + + case Xpath: + { + static const unsigned short staticallyStoredXpath[] = + { + 120, 112, 97, 116, 104, 0 + }; + data = staticallyStoredXpath; + length = 5; + break; + } + + default: + /* It's either the default token, or an undefined enum + * value. We silence a compiler warning, and return the + * empty string. */ + ; + } + + union + { + const unsigned short *data; + const QChar *asQChar; + } converter; + converter.data = data; + + return QString::fromRawData(converter.asQChar, length); + } + +QT_END_NAMESPACE + diff --git a/src/xmlpatterns/schema/qxsdschematoken_p.h b/src/xmlpatterns/schema/qxsdschematoken_p.h new file mode 100644 index 0000000..8cb1e76 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdschematoken_p.h @@ -0,0 +1,168 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +/* NOTE: This file is AUTO GENERATED by qautomaton2cpp.xsl. */ + +#ifndef QPatternist_XsdSchemaToken_h +#define QPatternist_XsdSchemaToken_h + +#include + +QT_BEGIN_NAMESPACE + +class XsdSchemaToken + { + public: + enum NodeName + + { + NoKeyword, +Abstract, +All, +Alternative, +Annotation, +Any, +AnyAttribute, +Appinfo, +AppliesToEmpty, +Assert, +Assertion, +Attribute, +AttributeFormDefault, +AttributeGroup, +Base, +Block, +BlockDefault, +Choice, +Collapse, +ComplexContent, +ComplexType, +Default, +DefaultAttributes, +DefaultAttributesApply, +DefaultOpenContent, +Documentation, +Element, +ElementFormDefault, +Enumeration, +Extension, +Field, +Final, +FinalDefault, +Fixed, +Form, +FractionDigits, +Group, +Id, +Import, +Include, +ItemType, +Key, +Keyref, +Length, +List, +MaxExclusive, +MaxInclusive, +MaxLength, +MaxOccurs, +MemberTypes, +MinExclusive, +MinInclusive, +MinLength, +MinOccurs, +Mixed, +Mode, +Name, +Namespace, +Nillable, +NotNamespace, +NotQName, +Notation, +OpenContent, +Override, +Pattern, +Preserve, +ProcessContents, +Public, +Redefine, +Ref, +Refer, +Replace, +Restriction, +Schema, +SchemaLocation, +Selector, +Sequence, +SimpleContent, +SimpleType, +Source, +SubstitutionGroup, +System, +TargetNamespace, +Test, +TotalDigits, +Type, +Union, +Unique, +Use, +Value, +Version, +WhiteSpace, +XML_NS_SCHEMA_URI, +XPathDefaultNamespace, +XmlLanguage, +Xpath + }; + + static inline NodeName toToken(const QString &value); +static inline NodeName toToken(const QStringRef &value); +static NodeName toToken(const QChar *data, int length); +static QString toString(NodeName token); + + + private: + static inline NodeName classifier2(const QChar *data); +static inline NodeName classifier3(const QChar *data); +static inline NodeName classifier4(const QChar *data); +static inline NodeName classifier5(const QChar *data); +static inline NodeName classifier6(const QChar *data); +static inline NodeName classifier7(const QChar *data); +static inline NodeName classifier8(const QChar *data); +static inline NodeName classifier9(const QChar *data); +static inline NodeName classifier10(const QChar *data); +static inline NodeName classifier11(const QChar *data); +static inline NodeName classifier12(const QChar *data); +static inline NodeName classifier13(const QChar *data); +static inline NodeName classifier14(const QChar *data); +static inline NodeName classifier15(const QChar *data); +static inline NodeName classifier17(const QChar *data); +static inline NodeName classifier18(const QChar *data); +static inline NodeName classifier20(const QChar *data); +static inline NodeName classifier21(const QChar *data); +static inline NodeName classifier22(const QChar *data); +static inline NodeName classifier32(const QChar *data); + + }; + + inline XsdSchemaToken::NodeName XsdSchemaToken::toToken(const QString &value) + { + return toToken(value.constData(), value.length()); + } + + inline XsdSchemaToken::NodeName XsdSchemaToken::toToken(const QStringRef &value) + { + return toToken(value.constData(), value.length()); + } + + +QT_END_NAMESPACE + +#endif diff --git a/src/xmlpatterns/schema/qxsdschematypesfactory.cpp b/src/xmlpatterns/schema/qxsdschematypesfactory.cpp new file mode 100644 index 0000000..6cac0ff --- /dev/null +++ b/src/xmlpatterns/schema/qxsdschematypesfactory.cpp @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qxsdschematypesfactory_p.h" + +#include "qbasictypesfactory_p.h" +#include "qbuiltintypes_p.h" +#include "qderivedinteger_p.h" +#include "qderivedstring_p.h" +#include "qcommonnamespaces_p.h" +#include "qxsdschematoken_p.h" +#include "qxsdsimpletype_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +XsdSchemaTypesFactory::XsdSchemaTypesFactory(const NamePool::Ptr &namePool) + : m_namePool(namePool) +{ + m_types.reserve(3); + + const XsdFacet::Ptr whiteSpaceFacet(new XsdFacet()); + whiteSpaceFacet->setType(XsdFacet::WhiteSpace); + whiteSpaceFacet->setFixed(true); + whiteSpaceFacet->setValue(DerivedString::fromLexical(m_namePool, XsdSchemaToken::toString(XsdSchemaToken::Collapse))); + + const XsdFacet::Ptr minLengthFacet(new XsdFacet()); + minLengthFacet->setType(XsdFacet::MinimumLength); + minLengthFacet->setValue(DerivedInteger::fromLexical(namePool, QLatin1String("1"))); + + XsdFacet::Hash facets; + facets.insert(whiteSpaceFacet->type(), whiteSpaceFacet); + facets.insert(minLengthFacet->type(), minLengthFacet); + + { + const QXmlName typeName = m_namePool->allocateQName(CommonNamespaces::WXS, QLatin1String("NMTOKENS")); + const XsdSimpleType::Ptr type(new XsdSimpleType()); + type->setName(typeName); + type->setWxsSuperType(BuiltinTypes::xsAnySimpleType); + type->setCategory(XsdSimpleType::SimpleTypeList); + type->setItemType(BuiltinTypes::xsNMTOKEN); + type->setDerivationMethod(XsdSimpleType::DerivationRestriction); + type->setFacets(facets); + m_types.insert(typeName, type); + } + { + const QXmlName typeName = m_namePool->allocateQName(CommonNamespaces::WXS, QLatin1String("IDREFS")); + const XsdSimpleType::Ptr type(new XsdSimpleType()); + type->setName(typeName); + type->setWxsSuperType(BuiltinTypes::xsAnySimpleType); + type->setCategory(XsdSimpleType::SimpleTypeList); + type->setItemType(BuiltinTypes::xsIDREF); + type->setDerivationMethod(XsdSimpleType::DerivationRestriction); + type->setFacets(facets); + m_types.insert(typeName, type); + } + { + const QXmlName typeName = m_namePool->allocateQName(CommonNamespaces::WXS, QLatin1String("ENTITIES")); + const XsdSimpleType::Ptr type(new XsdSimpleType()); + type->setName(typeName); + type->setWxsSuperType(BuiltinTypes::xsAnySimpleType); + type->setCategory(XsdSimpleType::SimpleTypeList); + type->setItemType(BuiltinTypes::xsENTITY); + type->setDerivationMethod(XsdSimpleType::DerivationRestriction); + type->setFacets(facets); + m_types.insert(typeName, type); + } +} + +SchemaType::Ptr XsdSchemaTypesFactory::createSchemaType(const QXmlName name) const +{ + if (m_types.contains(name)) { + return m_types.value(name); + } else { + if (!m_basicTypesFactory) + m_basicTypesFactory = BasicTypesFactory::self(m_namePool); + + return m_basicTypesFactory->createSchemaType(name); + } +} + +SchemaType::Hash XsdSchemaTypesFactory::types() const +{ + return m_types; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdschematypesfactory_p.h b/src/xmlpatterns/schema/qxsdschematypesfactory_p.h new file mode 100644 index 0000000..4fcd5fb --- /dev/null +++ b/src/xmlpatterns/schema/qxsdschematypesfactory_p.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdSchemaTypesFactory_H +#define Patternist_XsdSchemaTypesFactory_H + +#include +#include "qschematypefactory_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + + /** + * @short Factory for creating schema types for the types defined in XSD. + * + * @ingroup Patternist_types + * @author Tobias Koenig + */ + class XsdSchemaTypesFactory : public SchemaTypeFactory + { + public: + /** + * Creates a new schema type factory. + * + * @param namePool The name pool all type names belong to. + */ + XsdSchemaTypesFactory(const NamePool::Ptr &namePool); + + /** + * Creates a primitive type for @p name. If @p name is not supported, + * @c null is returned. + * + * @note This does not handle user defined types, only builtin types. + */ + virtual SchemaType::Ptr createSchemaType(const QXmlName) const; + + /** + * Returns a hash of all available types. + */ + virtual SchemaType::Hash types() const; + + private: + /** + * A dictonary of all predefined schema types. + */ + SchemaType::Hash m_types; + + NamePool::Ptr m_namePool; + mutable SchemaTypeFactory::Ptr m_basicTypesFactory; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsdsimpletype.cpp b/src/xmlpatterns/schema/qxsdsimpletype.cpp new file mode 100644 index 0000000..2e5b7f5 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdsimpletype.cpp @@ -0,0 +1,118 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#include "qxsdsimpletype_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +QString XsdSimpleType::displayName(const NamePool::Ptr &np) const +{ + return np->displayName(name(np)); +} + +void XsdSimpleType::setWxsSuperType(const SchemaType::Ptr &type) +{ + m_superType = type; +} + +SchemaType::Ptr XsdSimpleType::wxsSuperType() const +{ + return m_superType; +} + +void XsdSimpleType::setContext(const NamedSchemaComponent::Ptr &component) +{ + m_context = component; +} + +NamedSchemaComponent::Ptr XsdSimpleType::context() const +{ + return m_context; +} + +void XsdSimpleType::setPrimitiveType(const AnySimpleType::Ptr &type) +{ + m_primitiveType = type; +} + +AnySimpleType::Ptr XsdSimpleType::primitiveType() const +{ + return m_primitiveType; +} + +void XsdSimpleType::setItemType(const AnySimpleType::Ptr &type) +{ + m_itemType = type; +} + +AnySimpleType::Ptr XsdSimpleType::itemType() const +{ + return m_itemType; +} + +void XsdSimpleType::setMemberTypes(const AnySimpleType::List &types) +{ + m_memberTypes = types; +} + +AnySimpleType::List XsdSimpleType::memberTypes() const +{ + return m_memberTypes; +} + +void XsdSimpleType::setFacets(const XsdFacet::Hash &facets) +{ + m_facets = facets; +} + +XsdFacet::Hash XsdSimpleType::facets() const +{ + return m_facets; +} + +void XsdSimpleType::setCategory(TypeCategory category) +{ + m_typeCategory = category; +} + +XsdSimpleType::TypeCategory XsdSimpleType::category() const +{ + return m_typeCategory; +} + +void XsdSimpleType::setDerivationMethod(DerivationMethod method) +{ + m_derivationMethod = method; +} + +XsdSimpleType::DerivationMethod XsdSimpleType::derivationMethod() const +{ + return m_derivationMethod; +} + +bool XsdSimpleType::isDefinedBySchema() const +{ + return true; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdsimpletype_p.h b/src/xmlpatterns/schema/qxsdsimpletype_p.h new file mode 100644 index 0000000..9ba34b6 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdsimpletype_p.h @@ -0,0 +1,189 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdSimpleType_H +#define Patternist_XsdSimpleType_H + +#include "qanysimpletype_p.h" +#include "qxsdfacet_p.h" +#include "qxsduserschematype_p.h" + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Represents a XSD simpleType object. + * + * This class represents the simpleType object of a XML schema as described + * here. + * + * It contains information from either a top-level simple type declaration (as child of a schema object) + * or a local simple type declaration (as descendant of an element or complexType object). + * + * @see XML Schema API reference + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdSimpleType : public XsdUserSchemaType + { + public: + typedef QExplicitlySharedDataPointer Ptr; + + /** + * Returns the display name of the simple type. + * + * @param namePool The name pool the type name is stored in. + */ + virtual QString displayName(const NamePool::Ptr &namePool) const; + + /** + * Sets the base @p type of the simple type. + * + * @see Base Type Definition + */ + void setWxsSuperType(const SchemaType::Ptr &type); + + /** + * Returns the base type of the simple type or an empty pointer if no base type is + * set. + */ + virtual SchemaType::Ptr wxsSuperType() const; + + /** + * Sets the context @p component of the simple type. + * + * @see Context Definition + */ + void setContext(const NamedSchemaComponent::Ptr &component); + + /** + * Returns the context component of the simple type. + */ + NamedSchemaComponent::Ptr context() const; + + /** + * Sets the primitive @p type of the simple type. + * + * The primitive type is only specified if the category is SimpleTypeAtomic. + * + * @see Primitive Type Definition + */ + void setPrimitiveType(const AnySimpleType::Ptr &type); + + /** + * Returns the primitive type of the simple type or an empty pointer if the category is + * not SimpleTypeAtomic. + */ + AnySimpleType::Ptr primitiveType() const; + + /** + * Sets the list item @p type of the simple type. + * + * The list item type is only specified if the category is SimpleTypeList. + * + * @see Item Type Definition + */ + void setItemType(const AnySimpleType::Ptr &type); + + /** + * Returns the list item type of the simple type or an empty pointer if the category is + * not SimpleTypeList. + */ + AnySimpleType::Ptr itemType() const; + + /** + * Sets the member @p types of the simple type. + * + * The member types are only specified if the category is SimpleTypeUnion. + * + * @see Member Types Definition + */ + void setMemberTypes(const AnySimpleType::List &types); + + /** + * Returns the list member types of the simple type or an empty list if the category is + * not SimpleTypeUnion. + */ + AnySimpleType::List memberTypes() const; + + /** + * Sets the @p facets of the simple type. + * + * @see Facets Definition + */ + void setFacets(const XsdFacet::Hash &facets); + + /** + * Returns the facets of the simple type. + */ + XsdFacet::Hash facets() const; + + /** + * Sets the @p category (variety) of the simple type. + * + * @see Variety Definition + */ + void setCategory(TypeCategory category); + + /** + * Returns the category (variety) of the simple type. + */ + virtual TypeCategory category() const; + + /** + * Sets the derivation @p method of the simple type. + * + * @see DerivationMethod + */ + void setDerivationMethod(DerivationMethod method); + + /** + * Returns the derivation method of the simple type. + */ + virtual DerivationMethod derivationMethod() const; + + /** + * Always returns @c true. + */ + virtual bool isDefinedBySchema() const; + + private: + SchemaType::Ptr m_superType; + NamedSchemaComponent::Ptr m_context; + AnySimpleType::Ptr m_primitiveType; + AnySimpleType::Ptr m_itemType; + AnySimpleType::List m_memberTypes; + XsdFacet::Hash m_facets; + TypeCategory m_typeCategory; + DerivationMethod m_derivationMethod; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsdstatemachine.cpp b/src/xmlpatterns/schema/qxsdstatemachine.cpp new file mode 100644 index 0000000..e40e55b --- /dev/null +++ b/src/xmlpatterns/schema/qxsdstatemachine.cpp @@ -0,0 +1,433 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +/* + * NOTE: This file is included by qxsdstatemachine_p.h + * if you need some includes, put them in qxsdstatemachine_p.h (outside of the namespace) + */ + +template +XsdStateMachine::XsdStateMachine() + : m_counter(50) +{ +} + +template +XsdStateMachine::XsdStateMachine(const NamePool::Ptr &namePool) + : m_namePool(namePool) + , m_counter(50) +{ +} + +template +typename XsdStateMachine::StateId XsdStateMachine::addState(StateType type) +{ +#ifndef QT_NO_DEBUG + // make sure we don't have two start states + if (type == StartState) { + QHashIterator it(m_states); + while (it.hasNext()) { + it.next(); + Q_ASSERT(it.value() != StartState && it.value() != StartEndState); + } + } +#endif // QT_NO_DEBUG + + // reserve new state id + const StateId id = ++m_counter; + m_states.insert(id, type); + + // if it is a start state, we make it to our current state + if (type == StartState || type == StartEndState) + m_currentState = id; + + return id; +} + +template +void XsdStateMachine::addTransition(StateId start, TransitionType transition, StateId end) +{ + QHash > &hash = m_transitions[start]; + QVector &states = hash[transition]; + if (!states.contains(end)) + states.append(end); +} + +template +void XsdStateMachine::addEpsilonTransition(StateId start, StateId end) +{ + QVector &states = m_epsilonTransitions[start]; + states.append(end); +} + +template +void XsdStateMachine::reset() +{ + // reset the machine to the start state + QHashIterator it(m_states); + while (it.hasNext()) { + it.next(); + if (it.value() == StartState || it.value() == StartEndState) { + m_currentState = it.key(); + return; + } + } + + Q_ASSERT(false); +} + +template +void XsdStateMachine::clear() +{ + m_states.clear(); + m_transitions.clear(); + m_epsilonTransitions.clear(); + m_currentState = -1; + m_counter = 50; +} + +template +bool XsdStateMachine::proceed(TransitionType transition) +{ + // check that we are not in an invalid state + if (!m_transitions.contains(m_currentState)) { + return false; + } + + // fetch the transition entry for the current state + const QHash > &entry = m_transitions[m_currentState]; + if (entry.contains(transition)) { // is there an transition for the given input? + m_currentState = entry.value(transition).first(); + m_lastTransition = transition; + return true; + } else { + return false; + } +} + +template +template +bool XsdStateMachine::proceed(InputType input) +{ + // check that we are not in an invalid state + if (!m_transitions.contains(m_currentState)) { + return false; + } + + // fetch the transition entry for the current state + const QHash > &entry = m_transitions[m_currentState]; + QHashIterator > it(entry); + while (it.hasNext()) { + it.next(); + if (inputEqualsTransition(input, it.key())) { + m_currentState = it.value().first(); + m_lastTransition = it.key(); + return true; + } + } + + return false; +} + +template +template +bool XsdStateMachine::inputEqualsTransition(InputType input, TransitionType transition) const +{ + return false; +} + +template +bool XsdStateMachine::inEndState() const +{ + // check if current state is an end state + return (m_states.value(m_currentState) == StartEndState || m_states.value(m_currentState) == EndState); +} + +template +TransitionType XsdStateMachine::lastTransition() const +{ + return m_lastTransition; +} + +template +typename XsdStateMachine::StateId XsdStateMachine::startState() const +{ + QHashIterator it(m_states); + while (it.hasNext()) { + it.next(); + if (it.value() == StartState || it.value() == StartEndState) + return it.key(); + } + + Q_ASSERT(false); // should never be reached + return -1; +} + +template +QString XsdStateMachine::transitionTypeToString(TransitionType type) const +{ + Q_UNUSED(type) + + return QString(); +} + +template +bool XsdStateMachine::outputGraph(QIODevice *device, const QString &graphName) const +{ + if (!device->isOpen()) { + qWarning("device must be open for writing"); + return false; + } + + QByteArray graph; + QTextStream s(&graph); + + QHashIterator > > it(m_transitions); + QHashIterator it3(m_states); + + s << "digraph " << graphName << " {\n"; + s << " mindist = 2.0\n"; + + // draw edges + while (it.hasNext()) { + it.next(); + + QHashIterator > it2(it.value()); + while (it2.hasNext()) { + it2.next(); + for (int i = 0; i < it2.value().count(); ++i) + s << " " << it.key() << " -> " << it2.value().at(i) << " [label=\"" << transitionTypeToString(it2.key()) << "\"]\n"; + } + } + + QHashIterator > it4(m_epsilonTransitions); + while (it4.hasNext()) { + it4.next(); + + const QVector states = it4.value(); + for (int i = 0; i < states.count(); ++i) + s << " " << it4.key() << " -> " << states.at(i) << " [label=\"ε\"]\n"; + } + + // draw node infos + while (it3.hasNext()) { + it3.next(); + + QString style; + if (it3.value() == StartState) { + style = QLatin1String("shape=circle, style=filled, color=blue"); + } else if (it3.value() == StartEndState) { + style = QLatin1String("shape=doublecircle, style=filled, color=blue"); + } else if (it3.value() == InternalState) { + style = QLatin1String("shape=circle, style=filled, color=red"); + } else if (it3.value() == EndState) { + style = QLatin1String("shape=doublecircle, style=filled, color=green"); + } + + s << " " << it3.key() << " [" << style << "]\n"; + } + + s << "}\n"; + + s.flush(); + + if (device->write(graph) == -1) + return false; + + return true; +} + + +template +typename XsdStateMachine::StateId XsdStateMachine::dfaStateForNfaState(QSet nfaState, + QList< QPair, StateId> > &stateTable, + XsdStateMachine &dfa) const +{ + // check whether we have the given state in our lookup table + // already, in that case simply return it + for (int i = 0; i < stateTable.count(); ++i) { + if (stateTable.at(i).first == nfaState) + return stateTable.at(i).second; + } + + // check if the NFA state set contains a Start or End + // state, in that case our new DFA state will be a + // Start or End state as well + StateType type = InternalState; + QSetIterator it(nfaState); + bool hasStartState = false; + bool hasEndState = false; + while (it.hasNext()) { + const StateId state = it.next(); + if (m_states.value(state) == EndState) { + hasEndState = true; + } else if (m_states.value(state) == StartState) { + hasStartState = true; + } + } + if (hasStartState) { + if (hasEndState) + type = StartEndState; + else + type = StartState; + } else if (hasEndState) { + type = EndState; + } + + // create the new DFA state + const StateId dfaState = dfa.addState(type); + + // add the new DFA state to the lookup table + stateTable.append(qMakePair, StateId>(nfaState, dfaState)); + + return dfaState; +} + + +template +QSet::StateId> XsdStateMachine::epsilonClosure(const QSet &input) const +{ + // every state can reach itself by epsilon transition, so include the input states + // in the result as well + QSet result = input; + + // add the input states to the list of to be processed states + QList workStates = input.toList(); + while (!workStates.isEmpty()) { // while there are states to be processed left... + + // dequeue one state from list + const StateId state = workStates.takeFirst(); + + // get the list of states that can be reached by the epsilon transition + // from the current 'state' + const QVector targetStates = m_epsilonTransitions.value(state); + for (int i = 0; i < targetStates.count(); ++i) { + // if we have this target state not in our result set yet... + if (!result.contains(targetStates.at(i))) { + // ... add it to the result set + result.insert(targetStates.at(i)); + + // add the target state to the list of to be processed states as well, + // as we want to have the epsilon transitions not only for the first + // level of following states + workStates.append(targetStates.at(i)); + } + } + } + + return result; +} + +template +QSet::StateId> XsdStateMachine::move(const QSet &states, TransitionType input) const +{ + QSet result; + + QSetIterator it(states); + while (it.hasNext()) { // iterate over all given states + const StateId state = it.next(); + + // get the transition table for the current state + const QHash > transitions = m_transitions.value(state); + + // get the target states for the given input + const QVector targetStates = transitions.value(input); + + // add all target states to the result + for (int i = 0; i < targetStates.size(); ++i) + result.insert(targetStates.at(i)); + } + + return result; +} + +template +XsdStateMachine XsdStateMachine::toDFA() const +{ + XsdStateMachine dfa(m_namePool); + dfa.m_counter = 100; + QList< QPair< QSet, StateId> > table; + QList< QSet > isMarked; + + // search the start state as the algorithm starts with it... + StateId startState = -1; + QHashIterator stateTypeIt(m_states); + while (stateTypeIt.hasNext()) { + stateTypeIt.next(); + if (stateTypeIt.value() == StartState) { + startState = stateTypeIt.key(); + break; + } + } + Q_ASSERT(startState != -1); + + // our list of state set that still have to be processed + QList< QSet > workStates; + + // add the start state to the list of to processed state sets + workStates.append(epsilonClosure(QSet() << startState)); + + while (!workStates.isEmpty()) { // as long as there are state sets to process left + + // enqueue set of states + const QSet states = workStates.takeFirst(); + + if (isMarked.contains(states)) // we processed this state set already + continue; + + // mark as processed + isMarked.append(states); + + // select a list of all inputs that are possible for + // the 'states' set + QList input; + + { + QSetIterator it(states); + while (it.hasNext()) { + input << m_transitions.value(it.next()).keys(); + } + } + + // get the state in DFA that corresponds to the 'states' set in the NFA + const StateId dfaBegin = dfaStateForNfaState(states, table, dfa); + + for (int i = 0; i < input.count(); ++i) { // for each possible input + // retrieve the states that can be reached from the 'states' set by the + // given input or by epsilon transition + const QSet followStates = epsilonClosure(move(states, input.at(i))); + + // get the state in DFA that corresponds to the 'followStates' set in the NFA + const StateId dfaEnd = dfaStateForNfaState(followStates, table, dfa); + + // adds a new transition to the DFA that corresponds to the transitions between + // 'states' and 'followStates' in the NFA + dfa.addTransition(dfaBegin, input.at(i), dfaEnd); + + // add the 'followStates' to the list of to be processed state sets + workStates.append(followStates); + } + } + + return dfa; +} + +template +QHash::StateId, typename XsdStateMachine::StateType> XsdStateMachine::states() const +{ + return m_states; +} + +template +QHash::StateId, QHash::StateId> > > XsdStateMachine::transitions() const +{ + return m_transitions; +} diff --git a/src/xmlpatterns/schema/qxsdstatemachine_p.h b/src/xmlpatterns/schema/qxsdstatemachine_p.h new file mode 100644 index 0000000..7988335 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdstatemachine_p.h @@ -0,0 +1,209 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdStateMachine_H +#define Patternist_XsdStateMachine_H + +#include "qnamepool_p.h" + +#include +#include +#include + +class QIODevice; + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short A state machine used for evaluation. + * + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + template + class XsdStateMachine + { + public: + typedef qint32 StateId; + + /** + * Describes the type of state. + */ + enum StateType + { + StartState, ///< The state the machine will start with. + StartEndState, ///< The state the machine will start with, can be end state as well. + InternalState, ///< Any state that is not start or end state. + EndState ///< Any state where the machine is allowed to stop. + }; + + /** + * Creates a new state machine object. + */ + XsdStateMachine(); + + /** + * Creates a new state machine object. + * + * The name pool to use for accessing object names. + */ + XsdStateMachine(const NamePool::Ptr &namePool); + + /** + * Adds a new state of the given @p type to the state machine. + * + * @return The id of the new state. + */ + StateId addState(StateType type); + + /** + * Adds a new @p transition to the state machine. + * + * @param start The start state. + * @param transition The transition to come from the start to the end state. + * @param end The end state. + */ + void addTransition(StateId start, TransitionType transition, StateId end); + + /** + * Adds a new epsilon @p transition to the state machine. + * + * @param start The start state. + * @param end The end state. + */ + void addEpsilonTransition(StateId start, StateId end); + + /** + * Resets the machine to the start state. + */ + void reset(); + + /** + * Removes all states and transitions from the state machine. + */ + void clear(); + + /** + * Continues execution of the machine with the given input @p transition. + * + * @return @c true if the transition was successfull, @c false otherwise. + */ + bool proceed(TransitionType transition); + + /** + * Continues execution of the machine with the given @p input. + * + * @note To use this method, inputEqualsTransition must be implemented + * to find the right transition to use. + * + * @return @c true if the transition was successfull, @c false otherwise. + */ + template + bool proceed(InputType input); + + /** + * Returns whether the given @p input matches the given @p transition. + */ + template + bool inputEqualsTransition(InputType input, TransitionType transition) const; + + /** + * Returns whether the machine is in an allowed end state. + */ + bool inEndState() const; + + /** + * Returns the last transition that was taken. + */ + TransitionType lastTransition() const; + + /** + * Returns the start state of the machine. + */ + StateId startState() const; + + /** + * This method should be redefined by template specialization for every + * concret TransitionType. + */ + QString transitionTypeToString(TransitionType type) const; + + /** + * Outputs the state machine in DOT format to the given + * output @p device. + */ + bool outputGraph(QIODevice *device, const QString &graphName) const; + + /** + * Returns a DFA that is equal to the NFA of the state machine. + */ + XsdStateMachine toDFA() const; + + /** + * Returns the information of all states of the state machine. + */ + QHash states() const; + + /** + * Returns the information of all transitions of the state machine. + */ + QHash > > transitions() const; + + private: + /** + * Returns the DFA state for the given @p nfaStat from the given @p stateTable. + * If there is no corresponding DFA state yet, a new one is created. + */ + StateId dfaStateForNfaState(QSet nfaState, QList< QPair< QSet, StateId> > &stateTable, XsdStateMachine &dfa) const; + + /** + * Returns the set of all states that can be reached from the set of @p input states + * by the epsilon transition. + */ + QSet epsilonClosure(const QSet &input) const; + + /** + * Returns the set of all states that can be reached from the set of given @p states + * by the given @p input. + */ + QSet move(const QSet &states, TransitionType input) const; + + NamePool::Ptr m_namePool; + QHash m_states; + QHash > > m_transitions; + QHash > m_epsilonTransitions; + StateId m_currentState; + qint32 m_counter; + TransitionType m_lastTransition; + }; + + #include "qxsdstatemachine.cpp" +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsdstatemachinebuilder.cpp b/src/xmlpatterns/schema/qxsdstatemachinebuilder.cpp new file mode 100644 index 0000000..866e010 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdstatemachinebuilder.cpp @@ -0,0 +1,230 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qxsdstatemachinebuilder_p.h" + +#include "qxsdelement_p.h" +#include "qxsdmodelgroup_p.h" +#include "qxsdschemahelper_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +/* + * This methods takes a list of objects and returns a list of list + * of all combinations the objects can be ordered. + * + * e.g. input = [ 1, 2, 3 ] + * output = [ + * [ 1, 2, 3 ], + * [ 1, 3, 2 ], + * [ 2, 1, 3 ], + * [ 2, 3, 1 ], + * [ 3, 1, 2 ], + * [ 3, 2, 1 ] + * ] + * + * The method is used to create all possible combinations for the particles + * in an model group. + */ +template +QList< QList > allCombinations(const QList &input) +{ + if (input.count() == 1) + return (QList< QList >() << input); + + QList< QList > result; + for (int i = 0; i < input.count(); ++i) { + QList subList = input; + T value = subList.takeAt(i); + + QList< QList > subLists = allCombinations(subList); + for (int j = 0; j < subLists.count(); ++j) { + subLists[j].prepend(value); + } + result << subLists; + } + + return result; +} + +XsdStateMachineBuilder::XsdStateMachineBuilder(XsdStateMachine *machine, const NamePool::Ptr &namePool, Mode mode) + : m_stateMachine(machine), m_namePool(namePool), m_mode(mode) +{ +} + +XsdStateMachine::StateId XsdStateMachineBuilder::reset() +{ + Q_ASSERT(m_stateMachine); + + m_stateMachine->clear(); + + return m_stateMachine->addState(XsdStateMachine::EndState); +} + +XsdStateMachine::StateId XsdStateMachineBuilder::addStartState(XsdStateMachine::StateId state) +{ + const XsdStateMachine::StateId startState = m_stateMachine->addState(XsdStateMachine::StartState); + m_stateMachine->addEpsilonTransition(startState, state); + + return startState; +} + +/* + * Create the FSA according to Algorithm Tp(S) from http://www.ltg.ed.ac.uk/~ht/XML_Europe_2003.html + */ +XsdStateMachine::StateId XsdStateMachineBuilder::buildParticle(const XsdParticle::Ptr &particle, XsdStateMachine::StateId endState) +{ + XsdStateMachine::StateId currentStartState = endState; + XsdStateMachine::StateId currentEndState = endState; + + // 2 + if (particle->maximumOccursUnbounded()) { + const XsdStateMachine::StateId t = m_stateMachine->addState(XsdStateMachine::InternalState); + const XsdStateMachine::StateId n = buildTerm(particle->term(), t); + + m_stateMachine->addEpsilonTransition(t, n); + m_stateMachine->addEpsilonTransition(n, endState); + + currentEndState = t; + currentStartState = t; + } else { // 3 + int count = (particle->maximumOccurs() - particle->minimumOccurs()); + if (count > 100) + count = 100; + + for (int i = 0; i < count; ++i) { + currentStartState = buildTerm(particle->term(), currentEndState); + m_stateMachine->addEpsilonTransition(currentStartState, endState); + currentEndState = currentStartState; + } + } + + int minOccurs = particle->minimumOccurs(); + if (minOccurs > 100) + minOccurs = 100; + + for (int i = 0; i < minOccurs; ++i) { + currentStartState = buildTerm(particle->term(), currentEndState); + currentEndState = currentStartState; + } + + return currentStartState; +} + +/* + * Create the FSA according to Algorithm Tt(S) from http://www.ltg.ed.ac.uk/~ht/XML_Europe_2003.html + */ +XsdStateMachine::StateId XsdStateMachineBuilder::buildTerm(const XsdTerm::Ptr &term, XsdStateMachine::StateId endState) +{ + if (term->isWildcard()) { // 1 + const XsdStateMachine::StateId b = m_stateMachine->addState(XsdStateMachine::InternalState); + m_stateMachine->addTransition(b, term, endState); + return b; + } else if (term->isElement()) { // 2 + const XsdStateMachine::StateId b = m_stateMachine->addState(XsdStateMachine::InternalState); + m_stateMachine->addTransition(b, term, endState); + + const XsdElement::Ptr element(term); + if (m_mode == CheckingMode) { + const XsdElement::List substGroups = element->substitutionGroups(); + for (int i = 0; i < substGroups.count(); ++i) + m_stateMachine->addTransition(b, substGroups.at(i), endState); + } else if (m_mode == ValidatingMode) { + const XsdElement::List substGroups = element->substitutionGroups(); + for (int i = 0; i < substGroups.count(); ++i) { + if (XsdSchemaHelper::substitutionGroupOkTransitive(element, substGroups.at(i), m_namePool)) + m_stateMachine->addTransition(b, substGroups.at(i), endState); + } + } + + return b; + } else if (term->isModelGroup()) { + const XsdModelGroup::Ptr group(term); + + if (group->compositor() == XsdModelGroup::ChoiceCompositor) { // 3 + const XsdStateMachine::StateId b = m_stateMachine->addState(XsdStateMachine::InternalState); + + for (int i = 0; i < group->particles().count(); ++i) { + const XsdParticle::Ptr particle(group->particles().at(i)); + if (particle->maximumOccurs() != 0) { + const XsdStateMachine::StateId state = buildParticle(particle, endState); + m_stateMachine->addEpsilonTransition(b, state); + } + } + + return b; + } else if (group->compositor() == XsdModelGroup::SequenceCompositor) { // 4 + XsdStateMachine::StateId currentStartState = endState; + XsdStateMachine::StateId currentEndState = endState; + + for (int i = (group->particles().count() - 1); i >= 0; --i) { // iterate reverse + const XsdParticle::Ptr particle(group->particles().at(i)); + if (particle->maximumOccurs() != 0) { + currentStartState = buildParticle(particle, currentEndState); + currentEndState = currentStartState; + } + } + + return currentStartState; + } else if (group->compositor() == XsdModelGroup::AllCompositor) { + const XsdStateMachine::StateId newStartState = m_stateMachine->addState(XsdStateMachine::InternalState); + + const QList list = allCombinations(group->particles()); + + for (int i = 0; i < list.count(); ++i) { + XsdStateMachine::StateId currentStartState = endState; + XsdStateMachine::StateId currentEndState = endState; + + const XsdParticle::List particles = list.at(i); + for (int j = (particles.count() - 1); j >= 0; --j) { // iterate reverse + const XsdParticle::Ptr particle(particles.at(j)); + if (particle->maximumOccurs() != 0) { + currentStartState = buildParticle(particle, currentEndState); + currentEndState = currentStartState; + } + } + m_stateMachine->addEpsilonTransition(newStartState, currentStartState); + } + + if (list.isEmpty()) + return endState; + else + return newStartState; + } + } + + Q_ASSERT(false); + return 0; +} + +static void internalParticleLookupMap(const XsdParticle::Ptr &particle, QHash &hash) +{ + hash.insert(particle->term(), particle); + + if (particle->term()->isModelGroup()) { + const XsdModelGroup::Ptr group(particle->term()); + const XsdParticle::List particles = group->particles(); + for (int i = 0; i < particles.count(); ++i) + internalParticleLookupMap(particles.at(i), hash); + } +} + +QHash XsdStateMachineBuilder::particleLookupMap(const XsdParticle::Ptr &particle) +{ + QHash result; + internalParticleLookupMap(particle, result); + + return result; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdstatemachinebuilder_p.h b/src/xmlpatterns/schema/qxsdstatemachinebuilder_p.h new file mode 100644 index 0000000..011153a --- /dev/null +++ b/src/xmlpatterns/schema/qxsdstatemachinebuilder_p.h @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdStateMachineBuilder_H +#define Patternist_XsdStateMachineBuilder_H + +#include "qxsdparticle_p.h" +#include "qxsdstatemachine_p.h" +#include "qxsdterm_p.h" + +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short A helper class to build up validation state machines. + * + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdStateMachineBuilder : public QSharedData + { + public: + typedef QExplicitlySharedDataPointer Ptr; + + enum Mode + { + CheckingMode, + ValidatingMode + }; + + /** + * Creates a new state machine builder. + * + * @param machine The state machine it should work on. + * @param namePool The name pool used by all schema components. + * @param mode The mode the machine shall be build for. + */ + XsdStateMachineBuilder(XsdStateMachine *machine, const NamePool::Ptr &namePool, Mode mode = CheckingMode); + + /** + * Resets the state machine. + * + * @returns The initial end state. + */ + XsdStateMachine::StateId reset(); + + /** + * Prepends a start state to the given @p state. + * That is needed to allow the conversion of the state machine from a FSA to a DFA. + */ + XsdStateMachine::StateId addStartState(XsdStateMachine::StateId state); + + /** + * Creates the state machine for the given @p particle that should have the + * given @p endState. + * + * @returns The new start state. + */ + XsdStateMachine::StateId buildParticle(const XsdParticle::Ptr &particle, XsdStateMachine::StateId endState); + + /** + * Creates the state machine for the given @p term that should have the + * given @p endState. + * + * @returns The new start state. + */ + XsdStateMachine::StateId buildTerm(const XsdTerm::Ptr &term, XsdStateMachine::StateId endState); + + /** + * Returns a hash that maps each term that appears inside @p particle, to the particle it belongs. + * + * @note These information are used by XsdParticleChecker to check particle inheritance. + */ + static QHash particleLookupMap(const XsdParticle::Ptr &particle); + + private: + XsdStateMachine *m_stateMachine; + NamePool::Ptr m_namePool; + Mode m_mode; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsdterm.cpp b/src/xmlpatterns/schema/qxsdterm.cpp new file mode 100644 index 0000000..1dbe34b --- /dev/null +++ b/src/xmlpatterns/schema/qxsdterm.cpp @@ -0,0 +1,38 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qxsdterm_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +bool XsdTerm::isElement() const +{ + return false; +} + +bool XsdTerm::isModelGroup() const +{ + return false; +} + +bool XsdTerm::isWildcard() const +{ + return false; +} + +bool XsdTerm::isReference() const +{ + return false; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdterm_p.h b/src/xmlpatterns/schema/qxsdterm_p.h new file mode 100644 index 0000000..f45d791 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdterm_p.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdTerm_H +#define Patternist_XsdTerm_H + +#include "qnamedschemacomponent_p.h" +#include "qxsdannotated_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short A base class for all particles of a model group. + * + * This class is the base class for all particles of a model group + * as the element, group or any tag, it is not supposed to + * be instantiated directly. + * + * @see XML Schema API reference + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdTerm : public NamedSchemaComponent, public XsdAnnotated + { + public: + typedef QExplicitlySharedDataPointer Ptr; + + /** + * Returns @c true if the term is an element, @c false otherwise. + */ + virtual bool isElement() const; + + /** + * Returns @c true if the term is a model group (group tag), @c false otherwise. + */ + virtual bool isModelGroup() const; + + /** + * Returns @c true if the term is a wildcard (any tag), @c false otherwise. + */ + virtual bool isWildcard() const; + + /** + * Returns @c true if the term is a reference, @c false otherwise. + * + * @note The reference term is only used internally as helper during type resolving. + */ + virtual bool isReference() const; + + protected: + /** + * This constructor only exists to ensure this class is subclassed. + */ + inline XsdTerm() {}; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsdtypechecker.cpp b/src/xmlpatterns/schema/qxsdtypechecker.cpp new file mode 100644 index 0000000..ab971a9 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdtypechecker.cpp @@ -0,0 +1,1308 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qxsdtypechecker_p.h" + +#include "qabstractdatetime_p.h" +#include "qbase64binary_p.h" +#include "qboolean_p.h" +#include "qdecimal_p.h" +#include "qderivedinteger_p.h" +#include "qduration_p.h" +#include "qgenericstaticcontext_p.h" +#include "qhexbinary_p.h" +#include "qnamespaceresolver_p.h" +#include "qpatternplatform_p.h" +#include "qqnamevalue_p.h" +#include "qvaluefactory_p.h" +#include "qxmlnamepool.h" +#include "qxsdschemahelper_p.h" +#include "qxsdschemamerger_p.h" +#include "qxsdstatemachine_p.h" + +#include "qxsdschemadebugger_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +XsdSchemaSourceLocationReflection::XsdSchemaSourceLocationReflection(const QSourceLocation &location) + : m_sourceLocation(location) +{ +} + +const SourceLocationReflection* XsdSchemaSourceLocationReflection::actualReflection() const +{ + return this; +} + +QSourceLocation XsdSchemaSourceLocationReflection::sourceLocation() const +{ + return m_sourceLocation; +} + + +static AnySimpleType::Ptr comparableType(const AnySimpleType::Ptr &type) +{ + if (!type->isDefinedBySchema()) { + return type; + } else { + const XsdSimpleType::Ptr simpleType(type); + if (type->category() == SchemaType::SimpleTypeAtomic) { + return simpleType->primitiveType(); + } else if (type->category() == SchemaType::SimpleTypeList) { + return simpleType->itemType(); + } else if (type->category() == SchemaType::SimpleTypeUnion) { + return simpleType->memberTypes().first(); + } + } + + Q_ASSERT(false); + return AnySimpleType::Ptr(); +} + +static int totalDigitsForSignedLongLong(long long value) +{ + QString number = QString::number(value); + if (number.startsWith(QLatin1Char('-'))) + number = number.mid(1); + + return number.length(); +} + +static int totalDigitsForUnsignedLongLong(unsigned long long value) +{ + const QString number = QString::number(value); + return number.length(); +} + +static int totalDigitsForDecimal(const QString &lexicalValue) +{ + const QLatin1Char zeroChar('0'); + const int length = lexicalValue.length() - 1; + + // strip leading zeros + int pos = 0; + while (lexicalValue.at(pos) == zeroChar && (pos != length)) + pos++; + + QString value = lexicalValue.mid(pos); + + // if contains '.' strip trailing zeros + if (value.contains(QLatin1Char('.'))) { + pos = value.length() - 1; + while (value.at(pos) == zeroChar) { + pos--; + } + + value = value.left(pos + 1); + } + + // check number of digits of remaining string + int totalDigits = 0; + for (int i = 0; i < value.count(); ++i) + if (value.at(i).isDigit()) + ++totalDigits; + + if (totalDigits == 0) + totalDigits = 1; + + return totalDigits; +} + +static int fractionDigitsForDecimal(const QString &lexicalValue) +{ + // we use the lexical value here, as the conversion to double might strip + // away decimal positions + + QString trimmedValue(lexicalValue.trimmed()); + const int pos = trimmedValue.indexOf(QLatin1Char('.')); + if (pos == -1) // no '.' -> 0 fraction digits + return 0; + else + return (trimmedValue.length() - pos - 1); +} + +XsdTypeChecker::XsdTypeChecker(const XsdSchemaContext::Ptr &context, const QVector &namespaceBindings, const QSourceLocation &location) + : m_context(context) + , m_namePool(m_context->namePool()) + , m_namespaceBindings(namespaceBindings) + , m_reflection(new XsdSchemaSourceLocationReflection(location)) +{ +} + +XsdTypeChecker::~XsdTypeChecker() +{ +} + +QString XsdTypeChecker::normalizedValue(const QString &value, const XsdFacet::Hash &facets) +{ + if (!facets.contains(XsdFacet::WhiteSpace)) + return value; + + const XsdFacet::Ptr whiteSpaceFacet = facets.value(XsdFacet::WhiteSpace); + + const DerivedString::Ptr facetValue = whiteSpaceFacet->value(); + const QString stringValue = facetValue->stringValue(); + if (stringValue == XsdSchemaToken::toString(XsdSchemaToken::Preserve)) + return value; + else if (stringValue == XsdSchemaToken::toString(XsdSchemaToken::Replace)) { + QString newValue(value); + newValue.replace(QLatin1Char('\t'), QLatin1Char(' ')); + newValue.replace(QLatin1Char('\n'), QLatin1Char(' ')); + newValue.replace(QLatin1Char('\r'), QLatin1Char(' ')); + + return newValue; + } else if (stringValue == XsdSchemaToken::toString(XsdSchemaToken::Collapse)) { + return value.simplified(); + } + + return value; +} + +XsdFacet::Hash XsdTypeChecker::mergedFacetsForType(const SchemaType::Ptr &type, const XsdSchemaContext::Ptr &context) +{ + if (!type) + return XsdFacet::Hash(); + + const XsdFacet::Hash baseFacets = mergedFacetsForType(type->wxsSuperType(), context); + const XsdFacet::Hash facets = context->facetsForType(type); + + XsdFacet::Hash result = baseFacets; + XsdFacet::HashIterator it(facets); + while (it.hasNext()) { + it.next(); + + result.insert(it.key(), it.value()); + } + + return result; +} + +bool XsdTypeChecker::isValidString(const QString &normalizedString, const AnySimpleType::Ptr &type, QString &errorMsg, AnySimpleType::Ptr *boundType) const +{ + if (type->name(m_namePool) == BuiltinTypes::xsAnySimpleType->name(m_namePool)) { + if (boundType) + *boundType = type; + + return true; + } + + if (!type->isDefinedBySchema()) { + // special QName check + if (BuiltinTypes::xsQName->wxsTypeMatches(type)) { + if (!XPathHelper::isQName(normalizedString)) { + errorMsg = QtXmlPatterns::tr("%1 is not valid according to %2").arg(formatData(normalizedString)).arg(formatType(m_namePool, type)); + return false; + } + } + + const AtomicValue::Ptr value = fromLexical(normalizedString, type, m_context, m_reflection); + if (value->hasError()) { + errorMsg = QtXmlPatterns::tr("%1 is not valid according to %2").arg(formatData(normalizedString)).arg(formatType(m_namePool, type)); + return false; + } + + if (!checkConstrainingFacets(value, normalizedString, type, errorMsg)) { + return false; + } + + if (boundType) + *boundType = type; + + } else { + const XsdSimpleType::Ptr simpleType(type); + + if (simpleType->category() == XsdSimpleType::SimpleTypeAtomic) { + AnySimpleType::Ptr targetType = simpleType->primitiveType(); + if (!simpleType->wxsSuperType()->isDefinedBySchema()) + targetType = simpleType->wxsSuperType(); + + const AtomicValue::Ptr value = fromLexical(normalizedString, targetType, m_context, m_reflection); + if (value->hasError()) { + errorMsg = QtXmlPatterns::tr("%1 is not valid according to %2").arg(formatData(normalizedString)).arg(formatType(m_namePool, targetType)); + return false; + } + + if (!checkConstrainingFacets(value, normalizedString, type, errorMsg)) { + return false; + } + + if (boundType) + *boundType = type; + + } else if (simpleType->category() == XsdSimpleType::SimpleTypeList) { + QStringList entries = normalizedString.split(QLatin1Char(' '), QString::SkipEmptyParts); + for (int i = 0; i < entries.count(); ++i) { + entries[i] = normalizedValue(entries.at(i), mergedFacetsForType(simpleType->itemType(), m_context)); + } + + if (!checkConstrainingFacetsList(entries, normalizedString, simpleType->itemType(), mergedFacetsForType(simpleType, m_context), errorMsg)) { + return false; + } + + for (int i = 0; i < entries.count(); ++i) { + if (!isValidString(entries.at(i), simpleType->itemType(), errorMsg)) { + return false; + } + } + + if (boundType) + *boundType = simpleType->itemType(); + + } else if (simpleType->category() == XsdSimpleType::SimpleTypeUnion) { + if (!checkConstrainingFacetsUnion(normalizedString, normalizedString, simpleType, mergedFacetsForType(simpleType, m_context), errorMsg)) { + return false; + } + + const AnySimpleType::List memberTypes = simpleType->memberTypes(); + + bool foundValidType = false; + for (int i = 0; i < memberTypes.count(); ++i) { + const XsdFacet::Hash mergedFacets = mergedFacetsForType(memberTypes.at(i), m_context); + if (isValidString(normalizedValue(normalizedString, mergedFacets), memberTypes.at(i), errorMsg)) { + foundValidType = true; + + if (boundType) + *boundType = memberTypes.at(i); + + break; + } + } + + if (!foundValidType) { + return false; + } + } + } + + return true; +} + +bool XsdTypeChecker::valuesAreEqual(const QString &value, const QString &otherValue, const AnySimpleType::Ptr &type) const +{ + const AnySimpleType::Ptr targetType = comparableType(type); + + // if the type is xs:anySimpleType we just do string comparison... + if (targetType->name(m_namePool) == BuiltinTypes::xsAnySimpleType->name(m_namePool)) + return (value == otherValue); + + if (BuiltinTypes::xsQName->wxsTypeMatches(type)) { + const QXmlName valueName = convertToQName(value); + const QXmlName otherValueName = convertToQName(otherValue); + + if (valueName == otherValueName) + return true; + } + + if (type->category() == SchemaType::SimpleTypeAtomic) { + // ... otherwise we use the casting platform for value comparison + const DerivedString::Ptr valueStr = DerivedString::fromLexical(m_namePool, value); + const DerivedString::Ptr otherValueStr = DerivedString::fromLexical(m_namePool, otherValue); + + return XsdSchemaHelper::constructAndCompare(valueStr, AtomicComparator::OperatorEqual, otherValueStr, targetType, m_context, m_reflection); + } else if (type->category() == SchemaType::SimpleTypeList) { + const QStringList values = value.split(QLatin1Char(' '), QString::SkipEmptyParts); + const QStringList otherValues = otherValue.split(QLatin1Char(' '), QString::SkipEmptyParts); + if (values.count() != otherValues.count()) + return false; + + for (int i = 0; i < values.count(); ++i) { + if (!valuesAreEqual(values.at(i), otherValues.at(i), XsdSimpleType::Ptr(type)->itemType())) + return false; + } + + return true; + } else if (type->category() == SchemaType::SimpleTypeUnion) { + const AnySimpleType::List memberTypes = XsdSimpleType::Ptr(type)->memberTypes(); + for (int i = 0; i < memberTypes.count(); ++i) { + if (valuesAreEqual(value, otherValue, memberTypes.at(i))) { + return true; + } + } + + return false; + } + + return false; +} + +bool XsdTypeChecker::checkConstrainingFacets(const AtomicValue::Ptr &value, const QString &lexicalValue, const AnySimpleType::Ptr &type, QString &errorMsg) const +{ + const XsdFacet::Hash facets = mergedFacetsForType(type, m_context); + + if (BuiltinTypes::xsString->wxsTypeMatches(type) || + BuiltinTypes::xsUntypedAtomic->wxsTypeMatches(type)) { + return checkConstrainingFacetsString(value->stringValue(), facets, BuiltinTypes::xsString, errorMsg); + } else if (BuiltinTypes::xsAnyURI->wxsTypeMatches(type)) { + return checkConstrainingFacetsString(value->stringValue(), facets, BuiltinTypes::xsAnyURI, errorMsg); + } else if (BuiltinTypes::xsNOTATION->wxsTypeMatches(type)) { + return checkConstrainingFacetsNotation(value->as()->qName(), facets, errorMsg); + } else if (BuiltinTypes::xsUnsignedByte->wxsTypeMatches(type) || + BuiltinTypes::xsUnsignedInt->wxsTypeMatches(type) || + BuiltinTypes::xsUnsignedLong->wxsTypeMatches(type) || + BuiltinTypes::xsUnsignedShort->wxsTypeMatches(type)) { + return checkConstrainingFacetsUnsignedInteger(value->as()->toUnsignedInteger(), lexicalValue, facets, errorMsg); + } else if (BuiltinTypes::xsInteger->wxsTypeMatches(type)) { + return checkConstrainingFacetsSignedInteger(value->as()->toInteger(), lexicalValue, facets, errorMsg); + } else if (BuiltinTypes::xsFloat->wxsTypeMatches(type) || + BuiltinTypes::xsDouble->wxsTypeMatches(type)) { + return checkConstrainingFacetsDouble(value->as()->toDouble(), lexicalValue, facets, errorMsg); + } else if (BuiltinTypes::xsDecimal->wxsTypeMatches(type)) { + return checkConstrainingFacetsDecimal(value, lexicalValue, facets, errorMsg); + } else if (BuiltinTypes::xsDateTime->wxsTypeMatches(type)) { + return checkConstrainingFacetsDateTime(value->as()->toDateTime(), lexicalValue, facets, BuiltinTypes::xsDateTime, errorMsg); + } else if (BuiltinTypes::xsDate->wxsTypeMatches(type)) { + return checkConstrainingFacetsDateTime(value->as()->toDateTime(), lexicalValue, facets, BuiltinTypes::xsDate, errorMsg); + } else if (BuiltinTypes::xsGYear->wxsTypeMatches(type)) { + return checkConstrainingFacetsDateTime(value->as()->toDateTime(), lexicalValue, facets, BuiltinTypes::xsGYear, errorMsg); + } else if (BuiltinTypes::xsGYearMonth->wxsTypeMatches(type)) { + return checkConstrainingFacetsDateTime(value->as()->toDateTime(), lexicalValue, facets, BuiltinTypes::xsGYearMonth, errorMsg); + } else if (BuiltinTypes::xsGMonth->wxsTypeMatches(type)) { + return checkConstrainingFacetsDateTime(value->as()->toDateTime(), lexicalValue, facets, BuiltinTypes::xsGMonth, errorMsg); + } else if (BuiltinTypes::xsGMonthDay->wxsTypeMatches(type)) { + return checkConstrainingFacetsDateTime(value->as()->toDateTime(), lexicalValue, facets, BuiltinTypes::xsGMonthDay, errorMsg); + } else if (BuiltinTypes::xsGDay->wxsTypeMatches(type)) { + return checkConstrainingFacetsDateTime(value->as()->toDateTime(), lexicalValue, facets, BuiltinTypes::xsGDay, errorMsg); + } else if (BuiltinTypes::xsTime->wxsTypeMatches(type)) { + return checkConstrainingFacetsDateTime(value->as()->toDateTime(), lexicalValue, facets, BuiltinTypes::xsTime, errorMsg); + } else if (BuiltinTypes::xsDuration->wxsTypeMatches(type)) { + return checkConstrainingFacetsDuration(value, lexicalValue, facets, errorMsg); + } else if (BuiltinTypes::xsBoolean->wxsTypeMatches(type)) { + return checkConstrainingFacetsBoolean(value->as()->value(), lexicalValue, facets, errorMsg); + } else if (BuiltinTypes::xsHexBinary->wxsTypeMatches(type)) { + return checkConstrainingFacetsBinary(value->as()->asByteArray(), facets, BuiltinTypes::xsHexBinary, errorMsg); + } else if (BuiltinTypes::xsBase64Binary->wxsTypeMatches(type)) { + return checkConstrainingFacetsBinary(value->as()->asByteArray(), facets, BuiltinTypes::xsBase64Binary, errorMsg); + } else if (BuiltinTypes::xsQName->wxsTypeMatches(type)) { + return checkConstrainingFacetsQName(value->as()->qName(), lexicalValue, facets, errorMsg); + } + + return true; +} + +bool XsdTypeChecker::checkConstrainingFacetsString(const QString &value, const XsdFacet::Hash &facets, const AnySimpleType::Ptr &type, QString &errorMsg) const +{ + if (facets.contains(XsdFacet::Length)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::Length); + const DerivedInteger::Ptr length = facet->value(); + if (length->toInteger() != value.length()) { + errorMsg = QtXmlPatterns::tr("string content does not match the length facet"); + return false; + } + } + if (facets.contains(XsdFacet::MinimumLength)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumLength); + const DerivedInteger::Ptr length = facet->value(); + if (length->toInteger() > value.length()) { + errorMsg = QtXmlPatterns::tr("string content does not match the minLength facet"); + return false; + } + } + if (facets.contains(XsdFacet::MaximumLength)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumLength); + const DerivedInteger::Ptr length = facet->value(); + if (length->toInteger() < value.length()) { + errorMsg = QtXmlPatterns::tr("string content does not match the maxLength facet"); + return false; + } + } + if (facets.contains(XsdFacet::Pattern)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern); + const AtomicValue::List multiValue = facet->multiValue(); + bool found = false; + for (int j = 0; j < multiValue.count(); ++j) { + const QString pattern = multiValue.at(j)->as >()->stringValue(); + const QRegExp exp = PatternPlatform::parsePattern(pattern, m_context, m_reflection); + if (exp.exactMatch(value)) { + found = true; + break; + } + } + + if (!found) { + errorMsg = QtXmlPatterns::tr("string content does not match pattern facet"); + return false; + } + } + if (facets.contains(XsdFacet::Enumeration)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration); + const DerivedString::Ptr valueStr = DerivedString::fromLexical(m_namePool, value); + + const AtomicValue::List multiValue = facet->multiValue(); + bool found = false; + for (int j = 0; j < multiValue.count(); ++j) { + if (XsdSchemaHelper::constructAndCompare(valueStr, AtomicComparator::OperatorEqual, multiValue.at(j), type, m_context, m_reflection)) { + found = true; + break; + } + } + + if (!found) { + errorMsg = QtXmlPatterns::tr("string content is not listed in the enumeration facet"); + return false; + } + } + if (facets.contains(XsdFacet::Assertion)) { + //TODO: implement + } + + return true; +} + +bool XsdTypeChecker::checkConstrainingFacetsSignedInteger(long long value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const +{ + if (facets.contains(XsdFacet::MaximumInclusive)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumInclusive); + const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as >()->stringValue(), BuiltinTypes::xsLong, m_context, m_reflection); + if (facetValue->toInteger() < value) { + errorMsg = QtXmlPatterns::tr("signed integer content does not match the maxInclusive facet"); + return false; + } + } + if (facets.contains(XsdFacet::MaximumExclusive)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumExclusive); + const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as >()->stringValue(), BuiltinTypes::xsLong, m_context, m_reflection); + if (facetValue->toInteger() <= value) { + errorMsg = QtXmlPatterns::tr("signed integer content does not match the maxExclusive facet"); + return false; + } + } + if (facets.contains(XsdFacet::MinimumInclusive)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumInclusive); + const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as >()->stringValue(), BuiltinTypes::xsLong, m_context, m_reflection); + if (facetValue->toInteger() > value) { + errorMsg = QtXmlPatterns::tr("signed integer content does not match the minInclusive facet"); + return false; + } + } + if (facets.contains(XsdFacet::MinimumExclusive)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumExclusive); + const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as >()->stringValue(), BuiltinTypes::xsLong, m_context, m_reflection); + if (facetValue->toInteger() >= value) { + errorMsg = QtXmlPatterns::tr("signed integer content does not match the minExclusive facet"); + return false; + } + } + if (facets.contains(XsdFacet::Enumeration)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration); + const DerivedString::Ptr valueStr = DerivedString::fromLexical(m_namePool, QString::number(value)); + + const AtomicValue::List multiValue = facet->multiValue(); + bool found = false; + for (int j = 0; j < multiValue.count(); ++j) { + if (XsdSchemaHelper::constructAndCompare(valueStr, AtomicComparator::OperatorEqual, multiValue.at(j), BuiltinTypes::xsLong, m_context, m_reflection)) { + found = true; + break; + } + } + + if (!found) { + errorMsg = QtXmlPatterns::tr("signed integer content is not listed in the enumeration facet"); + return false; + } + } + if (facets.contains(XsdFacet::Pattern)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern); + const AtomicValue::List multiValue = facet->multiValue(); + bool found = false; + for (int j = 0; j < multiValue.count(); ++j) { + const QString pattern = multiValue.at(j)->as >()->stringValue(); + const QRegExp exp = PatternPlatform::parsePattern(pattern, m_context, m_reflection); + if (exp.exactMatch(lexicalValue)) { + found = true; + break; + } + } + + if (!found) { + errorMsg = QtXmlPatterns::tr("signed integer content does not match pattern facet"); + return false; + } + } + if (facets.contains(XsdFacet::TotalDigits)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::TotalDigits); + const DerivedInteger::Ptr facetValue = facet->value(); + + if (totalDigitsForSignedLongLong(value) > facetValue->toInteger()) { + errorMsg = QtXmlPatterns::tr("signed integer content does not match in the totalDigits facet"); + return false; + } + } + if (facets.contains(XsdFacet::Assertion)) { + //TODO: implement + } + + return true; +} + +bool XsdTypeChecker::checkConstrainingFacetsUnsignedInteger(unsigned long long value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const +{ + if (facets.contains(XsdFacet::MaximumInclusive)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumInclusive); + const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as >()->stringValue(), BuiltinTypes::xsUnsignedLong, m_context, m_reflection); + if (facetValue->toUnsignedInteger() < value) { + errorMsg = QtXmlPatterns::tr("unsigned integer content does not match the maxInclusive facet"); + return false; + } + } + if (facets.contains(XsdFacet::MaximumExclusive)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumExclusive); + const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as >()->stringValue(), BuiltinTypes::xsUnsignedLong, m_context, m_reflection); + if (facetValue->toUnsignedInteger() <= value) { + errorMsg = QtXmlPatterns::tr("unsigned integer content does not match the maxExclusive facet"); + return false; + } + } + if (facets.contains(XsdFacet::MinimumInclusive)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumInclusive); + const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as >()->stringValue(), BuiltinTypes::xsUnsignedLong, m_context, m_reflection); + if (facetValue->toUnsignedInteger() > value) { + errorMsg = QtXmlPatterns::tr("unsigned integer content does not match the minInclusive facet"); + return false; + } + } + if (facets.contains(XsdFacet::MinimumExclusive)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumExclusive); + const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as >()->stringValue(), BuiltinTypes::xsUnsignedLong, m_context, m_reflection); + if (facetValue->toUnsignedInteger() >= value) { + errorMsg = QtXmlPatterns::tr("unsigned integer content does not match the minExclusive facet"); + return false; + } + } + if (facets.contains(XsdFacet::Enumeration)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration); + const DerivedString::Ptr valueStr = DerivedString::fromLexical(m_namePool, QString::number(value)); + + const AtomicValue::List multiValue = facet->multiValue(); + bool found = false; + for (int j = 0; j < multiValue.count(); ++j) { + if (XsdSchemaHelper::constructAndCompare(valueStr, AtomicComparator::OperatorEqual, multiValue.at(j), BuiltinTypes::xsUnsignedLong, m_context, m_reflection)) { + found = true; + break; + } + } + + if (!found) { + errorMsg = QtXmlPatterns::tr("unsigned integer content is not listed in the enumeration facet"); + return false; + } + } + if (facets.contains(XsdFacet::Pattern)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern); + const AtomicValue::List multiValue = facet->multiValue(); + bool found = false; + for (int j = 0; j < multiValue.count(); ++j) { + const QString pattern = multiValue.at(j)->as >()->stringValue(); + const QRegExp exp = PatternPlatform::parsePattern(pattern, m_context, m_reflection); + if (exp.exactMatch(lexicalValue)) { + found = true; + break; + } + } + + if (!found) { + errorMsg = QtXmlPatterns::tr("unsigned integer content does not match pattern facet"); + return false; + } + } + if (facets.contains(XsdFacet::TotalDigits)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::TotalDigits); + const DerivedInteger::Ptr facetValue = facet->value(); + + if (totalDigitsForUnsignedLongLong(value) > facetValue->toInteger()) { + errorMsg = QtXmlPatterns::tr("unsigned integer content does not match in the totalDigits facet"); + return false; + } + } + if (facets.contains(XsdFacet::Assertion)) { + //TODO: implement + } + + return true; +} + +bool XsdTypeChecker::checkConstrainingFacetsDouble(double value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const +{ + if (facets.contains(XsdFacet::MaximumInclusive)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumInclusive); + const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as >()->stringValue(), BuiltinTypes::xsDouble, m_context, m_reflection); + if (facetValue->toDouble() < value) { + errorMsg = QtXmlPatterns::tr("double content does not match the maxInclusive facet"); + return false; + } + } + if (facets.contains(XsdFacet::MaximumExclusive)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumExclusive); + const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as >()->stringValue(), BuiltinTypes::xsDouble, m_context, m_reflection); + if (facetValue->toDouble() <= value) { + errorMsg = QtXmlPatterns::tr("double content does not match the maxExclusive facet"); + return false; + } + } + if (facets.contains(XsdFacet::MinimumInclusive)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumInclusive); + const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as >()->stringValue(), BuiltinTypes::xsDouble, m_context, m_reflection); + if (facetValue->toDouble() > value) { + errorMsg = QtXmlPatterns::tr("double content does not match the minInclusive facet"); + return false; + } + } + if (facets.contains(XsdFacet::MinimumExclusive)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumExclusive); + const Numeric::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as >()->stringValue(), BuiltinTypes::xsDouble, m_context, m_reflection); + if (facetValue->toDouble() >= value) { + errorMsg = QtXmlPatterns::tr("double content does not match the minExclusive facet"); + return false; + } + } + if (facets.contains(XsdFacet::Enumeration)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration); + const DerivedString::Ptr valueStr = DerivedString::fromLexical(m_namePool, QString::number(value)); + + const AtomicValue::List multiValue = facet->multiValue(); + bool found = false; + for (int j = 0; j < multiValue.count(); ++j) { + if (XsdSchemaHelper::constructAndCompare(valueStr, AtomicComparator::OperatorEqual, multiValue.at(j), BuiltinTypes::xsDouble, m_context, m_reflection)) { + found = true; + break; + } + } + + if (!found) { + errorMsg = QtXmlPatterns::tr("double content is not listed in the enumeration facet"); + return false; + } + } + if (facets.contains(XsdFacet::Pattern)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern); + const AtomicValue::List multiValue = facet->multiValue(); + bool found = false; + for (int j = 0; j < multiValue.count(); ++j) { + const QString pattern = multiValue.at(j)->as >()->stringValue(); + const QRegExp exp = PatternPlatform::parsePattern(pattern, m_context, m_reflection); + if (exp.exactMatch(lexicalValue)) { + found = true; + break; + } + } + + if (!found) { + errorMsg = QtXmlPatterns::tr("double content does not match pattern facet"); + return false; + } + } + if (facets.contains(XsdFacet::Assertion)) { + //TODO: implement + } + + return true; +} + +bool XsdTypeChecker::checkConstrainingFacetsDecimal(const AtomicValue::Ptr &value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const +{ + if (facets.contains(XsdFacet::FractionDigits)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::FractionDigits); + const DerivedInteger::Ptr facetValue = facet->value(); + + if (fractionDigitsForDecimal(lexicalValue) > facetValue->toInteger()) { + errorMsg = QtXmlPatterns::tr("decimal content does not match in the fractionDigits facet"); + return false; + } + } + if (facets.contains(XsdFacet::TotalDigits)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::TotalDigits); + const DerivedInteger::Ptr facetValue = facet->value(); + + if (totalDigitsForDecimal(lexicalValue) > facetValue->toInteger()) { + errorMsg = QtXmlPatterns::tr("decimal content does not match in the totalDigits facet"); + return false; + } + } + + return checkConstrainingFacetsDouble(value->as()->toDouble(), lexicalValue, facets, errorMsg); +} + +bool XsdTypeChecker::checkConstrainingFacetsDateTime(const QDateTime &value, const QString &lexicalValue, const XsdFacet::Hash &facets, const AnySimpleType::Ptr &type, QString &errorMsg) const +{ + if (facets.contains(XsdFacet::MaximumInclusive)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumInclusive); + const AbstractDateTime::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as >()->stringValue(), type, m_context, m_reflection); + if (facetValue->toDateTime() < value) { + errorMsg = QtXmlPatterns::tr("date time content does not match the maxInclusive facet"); + return false; + } + } + if (facets.contains(XsdFacet::MaximumExclusive)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumExclusive); + const AbstractDateTime::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as >()->stringValue(), type, m_context, m_reflection); + if (facetValue->toDateTime() <= value) { + errorMsg = QtXmlPatterns::tr("date time content does not match the maxExclusive facet"); + return false; + } + } + if (facets.contains(XsdFacet::MinimumInclusive)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumInclusive); + const AbstractDateTime::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as >()->stringValue(), type, m_context, m_reflection); + if (facetValue->toDateTime() > value) { + errorMsg = QtXmlPatterns::tr("date time content does not match the minInclusive facet"); + return false; + } + } + if (facets.contains(XsdFacet::MinimumExclusive)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumExclusive); + const AbstractDateTime::Ptr facetValue = ValueFactory::fromLexical(facet->value()->as >()->stringValue(), type, m_context, m_reflection); + if (facetValue->toDateTime() >= value) { + errorMsg = QtXmlPatterns::tr("date time content does not match the minExclusive facet"); + return false; + } + } + if (facets.contains(XsdFacet::Enumeration)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration); + + const AtomicValue::List multiValue = facet->multiValue(); + bool found = false; + for (int j = 0; j < multiValue.count(); ++j) { + const AbstractDateTime::Ptr facetValue = ValueFactory::fromLexical(multiValue.at(j)->as >()->stringValue(), type, m_context, m_reflection); + if (facetValue->toDateTime() == value) { + found = true; + break; + } + } + + if (!found) { + errorMsg = QtXmlPatterns::tr("date time content is not listed in the enumeration facet"); + return false; + } + } + if (facets.contains(XsdFacet::Pattern)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern); + const AtomicValue::List multiValue = facet->multiValue(); + bool found = false; + for (int j = 0; j < multiValue.count(); ++j) { + const QString pattern = multiValue.at(j)->as >()->stringValue(); + const QRegExp exp = PatternPlatform::parsePattern(pattern, m_context, m_reflection); + if (exp.exactMatch(lexicalValue)) { + found = true; + break; + } + } + + if (!found) { + errorMsg = QtXmlPatterns::tr("date time content does not match pattern facet"); + return false; + } + } + + return true; +} + +bool XsdTypeChecker::checkConstrainingFacetsDuration(const AtomicValue::Ptr&, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const +{ + if (facets.contains(XsdFacet::MaximumInclusive)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumInclusive); + const DerivedString::Ptr value = DerivedString::fromLexical(m_namePool, lexicalValue); + + if (XsdSchemaHelper::constructAndCompare(facets.value(XsdFacet::MaximumInclusive)->value(), AtomicComparator::OperatorLessThan, value, BuiltinTypes::xsDuration, m_context, m_reflection)) { + errorMsg = QtXmlPatterns::tr("duration content does not match the maxInclusive facet"); + return false; + } + } + if (facets.contains(XsdFacet::MaximumExclusive)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumExclusive); + const DerivedString::Ptr value = DerivedString::fromLexical(m_namePool, lexicalValue); + + if (XsdSchemaHelper::constructAndCompare(facets.value(XsdFacet::MaximumExclusive)->value(), AtomicComparator::OperatorLessOrEqual, value, BuiltinTypes::xsDuration, m_context, m_reflection)) { + errorMsg = QtXmlPatterns::tr("duration content does not match the maxExclusive facet"); + return false; + } + } + if (facets.contains(XsdFacet::MinimumInclusive)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumInclusive); + const DerivedString::Ptr value = DerivedString::fromLexical(m_namePool, lexicalValue); + + if (XsdSchemaHelper::constructAndCompare(facets.value(XsdFacet::MinimumInclusive)->value(), AtomicComparator::OperatorGreaterThan, value, BuiltinTypes::xsDuration, m_context, m_reflection)) { + errorMsg = QtXmlPatterns::tr("duration content does not match the minInclusive facet"); + return false; + } + } + if (facets.contains(XsdFacet::MinimumExclusive)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumExclusive); + const DerivedString::Ptr value = DerivedString::fromLexical(m_namePool, lexicalValue); + + if (XsdSchemaHelper::constructAndCompare(facets.value(XsdFacet::MinimumExclusive)->value(), AtomicComparator::OperatorGreaterOrEqual, value, BuiltinTypes::xsDuration, m_context, m_reflection)) { + errorMsg = QtXmlPatterns::tr("duration content does not match the minExclusive facet"); + return false; + } + } + if (facets.contains(XsdFacet::Enumeration)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration); + const DerivedString::Ptr value = DerivedString::fromLexical(m_namePool, lexicalValue); + + const AtomicValue::List multiValue = facet->multiValue(); + bool found = false; + for (int j = 0; j < multiValue.count(); ++j) { + if (XsdSchemaHelper::constructAndCompare(multiValue.at(j), AtomicComparator::OperatorEqual, value, BuiltinTypes::xsDuration, m_context, m_reflection)) { + found = true; + break; + } + } + + if (!found) { + errorMsg = QtXmlPatterns::tr("duration content is not listed in the enumeration facet"); + return false; + } + } + if (facets.contains(XsdFacet::Pattern)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern); + const AtomicValue::List multiValue = facet->multiValue(); + bool found = false; + for (int j = 0; j < multiValue.count(); ++j) { + const QString pattern = multiValue.at(j)->as >()->stringValue(); + const QRegExp exp = PatternPlatform::parsePattern(pattern, m_context, m_reflection); + if (exp.exactMatch(lexicalValue)) { + found = true; + break; + } + } + + if (!found) { + errorMsg = QtXmlPatterns::tr("duration content does not match pattern facet"); + return false; + } + } + if (facets.contains(XsdFacet::Assertion)) { + //TODO: implement + } + + return true; +} + +bool XsdTypeChecker::checkConstrainingFacetsBoolean(bool, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const +{ + if (facets.contains(XsdFacet::Pattern)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern); + const AtomicValue::List multiValue = facet->multiValue(); + bool found = false; + for (int j = 0; j < multiValue.count(); ++j) { + const QString pattern = multiValue.at(j)->as >()->stringValue(); + const QRegExp exp = PatternPlatform::parsePattern(pattern, m_context, m_reflection); + if (exp.exactMatch(lexicalValue)) { + found = true; + break; + } + } + + if (!found) { + errorMsg = QtXmlPatterns::tr("boolean content does not match pattern facet"); + return false; + } + } + if (facets.contains(XsdFacet::Assertion)) { + //TODO: implement + } + + return true; +} + +bool XsdTypeChecker::checkConstrainingFacetsBinary(const QByteArray &value, const XsdFacet::Hash &facets, const AnySimpleType::Ptr &type, QString &errorMsg) const +{ + if (facets.contains(XsdFacet::Length)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::Length); + const DerivedInteger::Ptr length = facet->value(); + if (length->toInteger() != value.length()) { + errorMsg = QtXmlPatterns::tr("binary content does not match the length facet"); + return false; + } + } + if (facets.contains(XsdFacet::MinimumLength)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::MinimumLength); + const DerivedInteger::Ptr length = facet->value(); + if (length->toInteger() > value.length()) { + errorMsg = QtXmlPatterns::tr("binary content does not match the minLength facet"); + return false; + } + } + if (facets.contains(XsdFacet::MaximumLength)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::MaximumLength); + const DerivedInteger::Ptr length = facet->value(); + if (length->toInteger() < value.length()) { + errorMsg = QtXmlPatterns::tr("binary content does not match the maxLength facet"); + return false; + } + } + if (facets.contains(XsdFacet::Enumeration)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration); + const AtomicValue::List multiValue = facet->multiValue(); + bool found = false; + for (int j = 0; j < multiValue.count(); ++j) { + const Base64Binary::Ptr binary = ValueFactory::fromLexical(multiValue.at(j)->as >()->stringValue(), type, m_context, m_reflection); + const QByteArray facetValue = binary->as()->asByteArray(); + if (value == facetValue) { + found = true; + break; + } + } + + if (!found) { + errorMsg = QtXmlPatterns::tr("binary content is not listed in the enumeration facet"); + return false; + } + } + if (facets.contains(XsdFacet::Pattern)) { + //TODO: implement + } + if (facets.contains(XsdFacet::Assertion)) { + //TODO: implement + } + + return true; +} + +bool XsdTypeChecker::checkConstrainingFacetsQName(const QXmlName &value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const +{ + if (facets.contains(XsdFacet::Length)) { + // always true + } + if (facets.contains(XsdFacet::MinimumLength)) { + // always true + } + if (facets.contains(XsdFacet::MaximumLength)) { + // always true + } + if (facets.contains(XsdFacet::Enumeration)) { + if (!XPathHelper::isQName(lexicalValue)) { + errorMsg = QtXmlPatterns::tr("invalid QName content: %1").arg(formatData(lexicalValue)); + return false; + } + + const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration); + const AtomicValue::List multiValue = facet->multiValue(); + bool found = false; + for (int j = 0; j < multiValue.count(); ++j) { + const QXmlName facetValue = multiValue.at(j)->as()->qName(); + + if (value == facetValue) { + found = true; + break; + } + } + + if (!found) { + errorMsg = QtXmlPatterns::tr("QName content is not listed in the enumeration facet"); + return false; + } + } + if (facets.contains(XsdFacet::Pattern)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern); + const AtomicValue::List multiValue = facet->multiValue(); + bool found = false; + for (int j = 0; j < multiValue.count(); ++j) { + const QString pattern = multiValue.at(j)->as >()->stringValue(); + const QRegExp exp = PatternPlatform::parsePattern(pattern, m_context, m_reflection); + if (exp.exactMatch(lexicalValue)) { + found = true; + break; + } + } + + if (!found) { + errorMsg = QtXmlPatterns::tr("QName content does not match pattern facet"); + return false; + } + } + if (facets.contains(XsdFacet::Assertion)) { + //TODO: implement + } + + return true; +} + +bool XsdTypeChecker::checkConstrainingFacetsNotation(const QXmlName &value, const XsdFacet::Hash &facets, QString &errorMsg) const +{ + if (facets.contains(XsdFacet::Length)) { + // deprecated by spec + } + if (facets.contains(XsdFacet::MinimumLength)) { + // deprecated by spec + } + if (facets.contains(XsdFacet::MaximumLength)) { + // deprecated by spec + } + if (facets.contains(XsdFacet::Enumeration)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration); + const AtomicValue::List multiValue = facet->multiValue(); + bool found = false; + for (int j = 0; j < multiValue.count(); ++j) { + const QXmlName facetValue = multiValue.at(j)->as()->qName(); + + if (value == facetValue) { + found = true; + break; + } + } + + if (!found) { + errorMsg = QtXmlPatterns::tr("notation content is not listed in the enumeration facet"); + return false; + } + } + if (facets.contains(XsdFacet::Pattern)) { + //TODO: implement + } + if (facets.contains(XsdFacet::Assertion)) { + //TODO: implement + } + + return true; +} + +bool XsdTypeChecker::checkConstrainingFacetsList(const QStringList &values, const QString &lexicalValue, const AnySimpleType::Ptr &itemType, const XsdFacet::Hash &facets, QString &errorMsg) const +{ + if (facets.contains(XsdFacet::Length)) { + const DerivedInteger::Ptr value = facets.value(XsdFacet::Length)->value(); + if (value->toInteger() != values.count()) { + errorMsg = QtXmlPatterns::tr("list content does not match length facet"); + return false; + } + } + if (facets.contains(XsdFacet::MinimumLength)) { + const DerivedInteger::Ptr value = facets.value(XsdFacet::MinimumLength)->value(); + if (value->toInteger() > values.count()) { + errorMsg = QtXmlPatterns::tr("list content does not match minLength facet"); + return false; + } + } + if (facets.contains(XsdFacet::MaximumLength)) { + const DerivedInteger::Ptr value = facets.value(XsdFacet::MaximumLength)->value(); + if (value->toInteger() < values.count()) { + errorMsg = QtXmlPatterns::tr("list content does not match maxLength facet"); + return false; + } + } + if (facets.contains(XsdFacet::Enumeration)) { + + bool found = false; + + // we have to handle lists with QName derived items differently + if (BuiltinTypes::xsQName->wxsTypeMatches(itemType) || BuiltinTypes::xsNOTATION->wxsTypeMatches(itemType)) { + // first convert the string values from the instance document to a list of QXmlName + QList instanceValues; + for (int i = 0; i < values.count(); ++i) { + instanceValues.append(convertToQName(values.at(i))); + } + + // fetch the values from the facet and create a list of QXmlNames for each of them + const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration); + + const AtomicValue::List multiValue = facet->multiValue(); + for (int i = 0; i < multiValue.count(); ++i) { + const QStringList facetValueList = multiValue.at(i)->as >()->stringValue().split(QLatin1Char(' '), QString::SkipEmptyParts); + + // create the list of atomic string values + QList facetValues; + for (int j = 0; j < facetValueList.count(); ++j) { + facetValues.append(convertToQName(facetValueList.at(j))); + } + + // check if both lists have the same length + if (instanceValues.count() != facetValues.count()) + continue; + + // check if both lists are equal, that means the contain equal items in the same order + bool matchesAll = true; + for (int j = 0; j < instanceValues.count(); ++j) { + if (instanceValues.at(j) != facetValues.at(j)) { + matchesAll = false; + break; + } + } + + if (matchesAll) { + found = true; + break; + } + } + } else { + // first convert the string values from the instance document to atomic values of type string + AtomicValue::List instanceValues; + for (int i = 0; i < values.count(); ++i) { + instanceValues.append(DerivedString::fromLexical(m_namePool, values.at(i))); + } + + // fetch the values from the facet and create a list of atomic string values for each of them + const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration); + + const AnySimpleType::Ptr targetType = comparableType(itemType); + + const AtomicValue::List multiValue = facet->multiValue(); + for (int i = 0; i < multiValue.count(); ++i) { + const QStringList facetValueList = multiValue.at(i)->as >()->stringValue().split(QLatin1Char(' '), QString::SkipEmptyParts); + + // create the list of atomic string values + AtomicValue::List facetValues; + for (int j = 0; j < facetValueList.count(); ++j) { + facetValues.append(DerivedString::fromLexical(m_namePool, facetValueList.at(j))); + } + + // check if both lists have the same length + if (instanceValues.count() != facetValues.count()) + continue; + + // check if both lists are equal, that means the contain equal items in the same order + bool matchesAll = true; + for (int j = 0; j < instanceValues.count(); ++j) { + if (!XsdSchemaHelper::constructAndCompare(instanceValues.at(j), AtomicComparator::OperatorEqual, facetValues.at(j), targetType, m_context, m_reflection)) { + matchesAll = false; + break; + } + } + + if (matchesAll) { + found = true; + break; + } + } + } + + if (!found) { + errorMsg = QtXmlPatterns::tr("list content is not listed in the enumeration facet"); + return false; + } + } + if (facets.contains(XsdFacet::Pattern)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern); + const AtomicValue::List multiValue = facet->multiValue(); + bool found = false; + for (int j = 0; j < multiValue.count(); ++j) { + const QString pattern = multiValue.at(j)->as >()->stringValue(); + const QRegExp exp = PatternPlatform::parsePattern(pattern, m_context, m_reflection); + if (exp.exactMatch(lexicalValue)) { + found = true; + break; + } + } + + if (!found) { + errorMsg = QtXmlPatterns::tr("list content does not match pattern facet"); + return false; + } + } + if (facets.contains(XsdFacet::Assertion)) { + //TODO: implement + } + + return true; +} + +bool XsdTypeChecker::checkConstrainingFacetsUnion(const QString &value, const QString &lexicalValue, const XsdSimpleType::Ptr &simpleType, const XsdFacet::Hash &facets, QString &errorMsg) const +{ + if (facets.contains(XsdFacet::Enumeration)) { + const AnySimpleType::List memberTypes = simpleType->memberTypes(); + + const XsdFacet::Ptr facet = facets.value(XsdFacet::Enumeration); + + // convert the instance value into an atomic string value + const DerivedString::Ptr valueString = DerivedString::fromLexical(m_namePool, value); + + // collect the facet values into a list of atomic string values + const AtomicValue::List facetValues = facet->multiValue(); + + // compare the instance value against the facetValues for each member type and + // search for a match + + bool found = false; + for (int i = 0; i < memberTypes.count(); ++i) { + const AnySimpleType::Ptr targetType = comparableType(memberTypes.at(i)); + for (int j = 0; j < facetValues.count(); ++j) { + if (XsdSchemaHelper::constructAndCompare(valueString, AtomicComparator::OperatorEqual, facetValues.at(j), targetType, m_context, m_reflection)) { + found = true; + break; + } + } + } + + if (!found) { + errorMsg = QtXmlPatterns::tr("union content is not listed in the enumeration facet"); + return false; + } + } + if (facets.contains(XsdFacet::Pattern)) { + const XsdFacet::Ptr facet = facets.value(XsdFacet::Pattern); + const AtomicValue::List multiValue = facet->multiValue(); + bool found = false; + for (int j = 0; j < multiValue.count(); ++j) { + const QString pattern = multiValue.at(j)->as >()->stringValue(); + const QRegExp exp = PatternPlatform::parsePattern(pattern, m_context, m_reflection); + if (exp.exactMatch(lexicalValue)) { + found = true; + break; + } + } + + if (!found) { + errorMsg = QtXmlPatterns::tr("union content does not match pattern facet"); + return false; + } + } + if (facets.contains(XsdFacet::Assertion)) { + //TODO: implement + } + + return true; +} + +AtomicValue::Ptr XsdTypeChecker::fromLexical(const QString &value, const SchemaType::Ptr &type, const ReportContext::Ptr &context, const SourceLocationReflection *const reflection) const +{ + if (type->name(m_namePool) == BuiltinTypes::xsNOTATION->name(m_namePool) || type->name(m_namePool) == BuiltinTypes::xsQName->name(m_namePool)) { + if (value.simplified().isEmpty()) + return ValidationError::createError(QtXmlPatterns::tr("data of type %1 are not allowed to be empty").arg(formatType(m_namePool, BuiltinTypes::xsNOTATION))); + + const QXmlName valueName = convertToQName(value); + return QNameValue::fromValue(m_namePool, valueName); + } else { + return ValueFactory::fromLexical(value, type, context, reflection); + } +} + +QXmlName XsdTypeChecker::convertToQName(const QString &name) const +{ + const int pos = name.indexOf(QLatin1Char(':')); + + QXmlName::PrefixCode prefixCode = 0; + QXmlName::NamespaceCode namespaceCode; + QXmlName::LocalNameCode localNameCode; + if (pos != -1) { + prefixCode = m_context->namePool()->allocatePrefix(name.left(pos)); + namespaceCode = StandardNamespaces::empty; + for (int i = 0; i < m_namespaceBindings.count(); ++i) { + if (m_namespaceBindings.at(i).prefix() == prefixCode) { + namespaceCode = m_namespaceBindings.at(i).namespaceURI(); + break; + } + } + localNameCode = m_context->namePool()->allocateLocalName(name.mid(pos + 1)); + } else { + prefixCode = StandardPrefixes::empty; + namespaceCode = StandardNamespaces::empty; + for (int i = 0; i < m_namespaceBindings.count(); ++i) { + if (m_namespaceBindings.at(i).prefix() == prefixCode) { + namespaceCode = m_namespaceBindings.at(i).namespaceURI(); + break; + } + } + localNameCode = m_context->namePool()->allocateLocalName(name); + } + + return QXmlName(namespaceCode, localNameCode, prefixCode); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdtypechecker_p.h b/src/xmlpatterns/schema/qxsdtypechecker_p.h new file mode 100644 index 0000000..2af20db --- /dev/null +++ b/src/xmlpatterns/schema/qxsdtypechecker_p.h @@ -0,0 +1,159 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdTypeChecker_H +#define Patternist_XsdTypeChecker_H + +#include + +#include "qschematype_p.h" +#include "qsourcelocationreflection_p.h" +#include "qxsdschemacontext_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QXmlQuery; + +namespace QPatternist +{ + /** + * @short An implementation of SourceLocationReflection that takes a QSourceLocation. + * + * This is a convenience class which provides a QSourceLocation with a SourceLocationReflection + * interface. + */ + class XsdSchemaSourceLocationReflection : public SourceLocationReflection + { + public: + XsdSchemaSourceLocationReflection(const QSourceLocation &location); + + virtual const SourceLocationReflection *actualReflection() const; + virtual QSourceLocation sourceLocation() const; + + private: + const QSourceLocation m_sourceLocation; + }; + + /** + * @short The class that provides methods for checking a string against a type. + * + * The class provides functionality for type-aware string handling. + */ + class XsdTypeChecker + { + public: + /** + * Creates a new type checker. + * + * @param context The schema context that is used for error reporting. + * @param namespaceBindings The namespace bindings that shall be used to check against xs:QName based types. + * @param location The source location that is used for error reporting. + */ + XsdTypeChecker(const XsdSchemaContext::Ptr &context, const QVector &namespaceBindings, const QSourceLocation &location); + + /** + * Destroys the type checker. + */ + ~XsdTypeChecker(); + + /** + * Returns all facets for the given @p type. + * + * The list of facets is created by following the type hierarchy from xs:anyType down to the given type + * and merging the facets in each step. + */ + static XsdFacet::Hash mergedFacetsForType(const SchemaType::Ptr &type, const XsdSchemaContext::Ptr &context); + + /** + * Returns the normalized value for the given @p value. + * + * The normalized value is the original value with all the white space facets + * applied on it. + * + * @param value The original value. + * @param facets The hash of all facets of the values type. + */ + static QString normalizedValue(const QString &value, const XsdFacet::Hash &facets); + + /** + * Checks whether the @p normalizedString is valid according the given @p type. + * + * @param normalizedString The string in normalized form (whitespace facets applied). + * @param type The type the string shall be tested against. + * @param errorMsg Contains the error message if the normalizedString does not match the type. + * @param boundType The type the data was bound to during validation. + * + * @note The @p boundType only differs from @p type if the type is derived from an based union value. + */ + bool isValidString(const QString &normalizedString, const AnySimpleType::Ptr &type, QString &errorMsg, AnySimpleType::Ptr *boundType = 0) const; + + /** + * Returns whether the given @p value and @p otherValue are of @p type and are equal. + */ + bool valuesAreEqual(const QString &value, const QString &otherValue, const AnySimpleType::Ptr &type) const; + + private: + Q_DISABLE_COPY(XsdTypeChecker) + + /** + * Checks the given value against the facets of @p type. + */ + bool checkConstrainingFacets(const AtomicValue::Ptr &value, const QString &lexicalValue, const AnySimpleType::Ptr &type, QString &errorMsg) const; + bool checkConstrainingFacetsString(const QString &value, const XsdFacet::Hash &facets, const AnySimpleType::Ptr &type, QString &errorMsg) const; + bool checkConstrainingFacetsSignedInteger(long long value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const; + bool checkConstrainingFacetsUnsignedInteger(unsigned long long value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const; + bool checkConstrainingFacetsDouble(double value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const; + bool checkConstrainingFacetsDecimal(const AtomicValue::Ptr &value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const; + bool checkConstrainingFacetsDateTime(const QDateTime &value, const QString &lexicalValue, const XsdFacet::Hash &facets, const AnySimpleType::Ptr &type, QString &errorMsg) const; + bool checkConstrainingFacetsDuration(const AtomicValue::Ptr &value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const; + bool checkConstrainingFacetsBoolean(bool value, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const; + bool checkConstrainingFacetsBinary(const QByteArray &value, const XsdFacet::Hash &facets, const AnySimpleType::Ptr &type, QString &errorMsg) const; + bool checkConstrainingFacetsQName(const QXmlName&, const QString &lexicalValue, const XsdFacet::Hash &facets, QString &errorMsg) const; + bool checkConstrainingFacetsNotation(const QXmlName &value, const XsdFacet::Hash &facets, QString &errorMsg) const; + bool checkConstrainingFacetsList(const QStringList &values, const QString &lexicalValue, const AnySimpleType::Ptr &itemType, const XsdFacet::Hash &facets, QString &errorMsg) const; + bool checkConstrainingFacetsUnion(const QString &value, const QString &lexicalValue, const XsdSimpleType::Ptr &simpleType, const XsdFacet::Hash &facets, QString &errorMsg) const; + + /** + * Creates an atomic value of @p type from the given string @p value. + */ + AtomicValue::Ptr fromLexical(const QString &value, const SchemaType::Ptr &type, const ReportContext::Ptr &context, const SourceLocationReflection *const reflection) const; + + /** + * Converts a qualified name into a QXmlName according to the namespace + * mappings of the current node. + */ + QXmlName convertToQName(const QString &name) const; + + XsdSchemaContext::Ptr m_context; + XsdSchema::Ptr m_schema; + const NamePool::Ptr m_namePool; + QVector m_namespaceBindings; + SourceLocationReflection* m_reflection; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsduserschematype.cpp b/src/xmlpatterns/schema/qxsduserschematype.cpp new file mode 100644 index 0000000..b8bf7e7 --- /dev/null +++ b/src/xmlpatterns/schema/qxsduserschematype.cpp @@ -0,0 +1,45 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +/* + * NOTE: This file is included by qxsduserschematype_p.h + * if you need some includes, put them in qxsduserschematype_p.h (outside of the namespace) + */ + +template +void XsdUserSchemaType::setName(const QXmlName &name) +{ + m_name = name; +} + +template +QXmlName XsdUserSchemaType::name(const NamePool::Ptr&) const +{ + return m_name; +} + +template +QString XsdUserSchemaType::displayName(const NamePool::Ptr &np) const +{ + return np->displayName(m_name); +} + +template +void XsdUserSchemaType::setDerivationConstraints(const SchemaType::DerivationConstraints &constraints) +{ + m_derivationConstraints = constraints; +} + +template +SchemaType::DerivationConstraints XsdUserSchemaType::derivationConstraints() const +{ + return m_derivationConstraints; +} diff --git a/src/xmlpatterns/schema/qxsduserschematype_p.h b/src/xmlpatterns/schema/qxsduserschematype_p.h new file mode 100644 index 0000000..ab70f91 --- /dev/null +++ b/src/xmlpatterns/schema/qxsduserschematype_p.h @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdUserSchemaType_H +#define Patternist_XsdUserSchemaType_H + +#include "qnamedschemacomponent_p.h" +#include "qschematype_p.h" +#include "qxsdannotated_p.h" + +template class QHash; +template class QList; + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short A base class for all user defined simple and complex types. + * + * This class was introduced to combine the SchemaType class and the + * NamedSchemaComponent class without explicit inheritance. + * + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + template + class XsdUserSchemaType : public TSuperClass, public NamedSchemaComponent, public XsdAnnotated + { + public: + typedef QExplicitlySharedDataPointer Ptr; + + /** + * Sets the @p name of the type. + */ + void setName(const QXmlName &name); + + /** + * Returns the name of the type. + * + * @param namePool The pool the name belongs to. + */ + virtual QXmlName name(const NamePool::Ptr &namePool) const; + + /** + * Returns the display name of the type. + * + * @param namePool The pool the name belongs to. + */ + virtual QString displayName(const NamePool::Ptr &namePool) const; + + /** + * Sets the derivation @p constraints of the type. + */ + void setDerivationConstraints(const SchemaType::DerivationConstraints &constraints); + + /** + * Returns the derivation constraints of the type. + */ + SchemaType::DerivationConstraints derivationConstraints() const; + + private: + QXmlName m_name; + SchemaType::DerivationConstraints m_derivationConstraints; + }; + + #include "qxsduserschematype.cpp" +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsdvalidatedxmlnodemodel.cpp b/src/xmlpatterns/schema/qxsdvalidatedxmlnodemodel.cpp new file mode 100644 index 0000000..8e1645a --- /dev/null +++ b/src/xmlpatterns/schema/qxsdvalidatedxmlnodemodel.cpp @@ -0,0 +1,185 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qxsdvalidatedxmlnodemodel_p.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +XsdValidatedXmlNodeModel::XsdValidatedXmlNodeModel(const QAbstractXmlNodeModel *model) + : m_internalModel(const_cast(model)) +{ +} + +XsdValidatedXmlNodeModel::~XsdValidatedXmlNodeModel() +{ +} + +QUrl XsdValidatedXmlNodeModel::baseUri(const QXmlNodeModelIndex &index) const +{ + return m_internalModel->baseUri(index); +} + +QUrl XsdValidatedXmlNodeModel::documentUri(const QXmlNodeModelIndex &index) const +{ + return m_internalModel->documentUri(index); +} + +QXmlNodeModelIndex::NodeKind XsdValidatedXmlNodeModel::kind(const QXmlNodeModelIndex &index) const +{ + return m_internalModel->kind(index); +} + +QXmlNodeModelIndex::DocumentOrder XsdValidatedXmlNodeModel::compareOrder(const QXmlNodeModelIndex &index, const QXmlNodeModelIndex &otherIndex) const +{ + return m_internalModel->compareOrder(index, otherIndex); +} + +QXmlNodeModelIndex XsdValidatedXmlNodeModel::root(const QXmlNodeModelIndex &index) const +{ + return m_internalModel->root(index); +} + +QXmlName XsdValidatedXmlNodeModel::name(const QXmlNodeModelIndex &index) const +{ + return m_internalModel->name(index); +} + +QString XsdValidatedXmlNodeModel::stringValue(const QXmlNodeModelIndex &index) const +{ + return m_internalModel->stringValue(index); +} + +QVariant XsdValidatedXmlNodeModel::typedValue(const QXmlNodeModelIndex &index) const +{ + return m_internalModel->typedValue(index); +} + +QExplicitlySharedDataPointer > XsdValidatedXmlNodeModel::iterate(const QXmlNodeModelIndex &index, QXmlNodeModelIndex::Axis axis) const +{ + return m_internalModel->iterate(index, axis); +} + +QPatternist::ItemIteratorPtr XsdValidatedXmlNodeModel::sequencedTypedValue(const QXmlNodeModelIndex &index) const +{ + return m_internalModel->sequencedTypedValue(index); +} + +QPatternist::ItemTypePtr XsdValidatedXmlNodeModel::type(const QXmlNodeModelIndex &index) const +{ + return m_internalModel->type(index); +} + +QXmlName::NamespaceCode XsdValidatedXmlNodeModel::namespaceForPrefix(const QXmlNodeModelIndex &index, const QXmlName::PrefixCode prefix) const +{ + return m_internalModel->namespaceForPrefix(index, prefix); +} + +bool XsdValidatedXmlNodeModel::isDeepEqual(const QXmlNodeModelIndex &index, const QXmlNodeModelIndex &otherIndex) const +{ + return m_internalModel->isDeepEqual(index, otherIndex); +} + +void XsdValidatedXmlNodeModel::sendNamespaces(const QXmlNodeModelIndex &index, QAbstractXmlReceiver *const receiver) const +{ + m_internalModel->sendNamespaces(index, receiver); +} + +QVector XsdValidatedXmlNodeModel::namespaceBindings(const QXmlNodeModelIndex &index) const +{ + return m_internalModel->namespaceBindings(index); +} + +QXmlNodeModelIndex XsdValidatedXmlNodeModel::elementById(const QXmlName &name) const +{ + return m_internalModel->elementById(name); +} + +QVector XsdValidatedXmlNodeModel::nodesByIdref(const QXmlName &name) const +{ + return m_internalModel->nodesByIdref(name); +} + +void XsdValidatedXmlNodeModel::copyNodeTo(const QXmlNodeModelIndex &index, QAbstractXmlReceiver *const receiver, const NodeCopySettings &settings) const +{ + return m_internalModel->copyNodeTo(index, receiver, settings); +} + +QXmlNodeModelIndex XsdValidatedXmlNodeModel::nextFromSimpleAxis(SimpleAxis axis, const QXmlNodeModelIndex &origin) const +{ + return m_internalModel->nextFromSimpleAxis(axis, origin); +} + +QVector XsdValidatedXmlNodeModel::attributes(const QXmlNodeModelIndex &index) const +{ + return m_internalModel->attributes(index); +} + +void XsdValidatedXmlNodeModel::setAssignedElement(const QXmlNodeModelIndex &index, const XsdElement::Ptr &element) +{ + m_assignedElements.insert(index, element); +} + +XsdElement::Ptr XsdValidatedXmlNodeModel::assignedElement(const QXmlNodeModelIndex &index) const +{ + if (m_assignedElements.contains(index)) + return m_assignedElements.value(index); + else + return XsdElement::Ptr(); +} + +void XsdValidatedXmlNodeModel::setAssignedAttribute(const QXmlNodeModelIndex &index, const XsdAttribute::Ptr &attribute) +{ + m_assignedAttributes.insert(index, attribute); +} + +XsdAttribute::Ptr XsdValidatedXmlNodeModel::assignedAttribute(const QXmlNodeModelIndex &index) const +{ + if (m_assignedAttributes.contains(index)) + return m_assignedAttributes.value(index); + else + return XsdAttribute::Ptr(); +} + +void XsdValidatedXmlNodeModel::setAssignedType(const QXmlNodeModelIndex &index, const SchemaType::Ptr &type) +{ + m_assignedTypes.insert(index, type); +} + +SchemaType::Ptr XsdValidatedXmlNodeModel::assignedType(const QXmlNodeModelIndex &index) const +{ + if (m_assignedTypes.contains(index)) + return m_assignedTypes.value(index); + else + return SchemaType::Ptr(); +} + +void XsdValidatedXmlNodeModel::addIdIdRefBinding(const QString &id, const NamedSchemaComponent::Ptr &binding) +{ + m_idIdRefBindings[id].insert(binding); +} + +QStringList XsdValidatedXmlNodeModel::idIdRefBindingIds() const +{ + return m_idIdRefBindings.keys(); +} + +QSet XsdValidatedXmlNodeModel::idIdRefBindings(const QString &id) const +{ + return m_idIdRefBindings.value(id); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdvalidatedxmlnodemodel_p.h b/src/xmlpatterns/schema/qxsdvalidatedxmlnodemodel_p.h new file mode 100644 index 0000000..579f41a --- /dev/null +++ b/src/xmlpatterns/schema/qxsdvalidatedxmlnodemodel_p.h @@ -0,0 +1,149 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdValidatedXmlNodeModel_H +#define Patternist_XsdValidatedXmlNodeModel_H + +#include "qabstractxmlnodemodel.h" + +#include "qabstractxmlforwarditerator_p.h" +#include "qitem_p.h" +#include "qschematype_p.h" +#include "qxsdelement_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short A delegate class that wraps around a QAbstractXmlNodeModel and provides + * additional validation specific information. + * + * This class represents the input XML document enriched with additional type + * information that has been assigned during validation. + * + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdValidatedXmlNodeModel : public QAbstractXmlNodeModel + { + public: + typedef QExplicitlySharedDataPointer Ptr; + typedef QList List; + + /** + * Creates a new validated xml node model. + */ + XsdValidatedXmlNodeModel(const QAbstractXmlNodeModel *model); + + /** + * Destroys the validated xml node model. + */ + virtual ~XsdValidatedXmlNodeModel(); + + virtual QUrl baseUri(const QXmlNodeModelIndex &ni) const; + virtual QUrl documentUri(const QXmlNodeModelIndex &ni) const; + virtual QXmlNodeModelIndex::NodeKind kind(const QXmlNodeModelIndex &ni) const; + virtual QXmlNodeModelIndex::DocumentOrder compareOrder(const QXmlNodeModelIndex &ni1, const QXmlNodeModelIndex &ni2) const; + virtual QXmlNodeModelIndex root(const QXmlNodeModelIndex &n) const; + virtual QXmlName name(const QXmlNodeModelIndex &ni) const; + virtual QString stringValue(const QXmlNodeModelIndex &n) const; + virtual QVariant typedValue(const QXmlNodeModelIndex &n) const; + virtual QExplicitlySharedDataPointer > iterate(const QXmlNodeModelIndex &ni, QXmlNodeModelIndex::Axis axis) const; + virtual QPatternist::ItemIteratorPtr sequencedTypedValue(const QXmlNodeModelIndex &ni) const; + virtual QPatternist::ItemTypePtr type(const QXmlNodeModelIndex &ni) const; + virtual QXmlName::NamespaceCode namespaceForPrefix(const QXmlNodeModelIndex &ni, const QXmlName::PrefixCode prefix) const; + virtual bool isDeepEqual(const QXmlNodeModelIndex &ni1, const QXmlNodeModelIndex &ni2) const; + virtual void sendNamespaces(const QXmlNodeModelIndex &n, QAbstractXmlReceiver *const receiver) const; + virtual QVector namespaceBindings(const QXmlNodeModelIndex &n) const; + virtual QXmlNodeModelIndex elementById(const QXmlName &NCName) const; + virtual QVector nodesByIdref(const QXmlName &NCName) const; + virtual void copyNodeTo(const QXmlNodeModelIndex &node, QAbstractXmlReceiver *const receiver, const NodeCopySettings &) const; + + /** + * Sets the @p element that is assigned to the xml node at @p index. + */ + void setAssignedElement(const QXmlNodeModelIndex &index, const XsdElement::Ptr &element); + + /** + * Returns the element that is assigned to the xml node at @p index. + */ + XsdElement::Ptr assignedElement(const QXmlNodeModelIndex &index) const; + + /** + * Sets the @p attribute that is assigned to the xml node at @p index. + */ + void setAssignedAttribute(const QXmlNodeModelIndex &index, const XsdAttribute::Ptr &attribute); + + /** + * Returns the attribute that is assigned to the xml node at @p index. + */ + XsdAttribute::Ptr assignedAttribute(const QXmlNodeModelIndex &index) const; + + /** + * Sets the @p type that is assigned to the xml node at @p index. + * + * @note The type can be a different than the type of the element or + * attribute that is assigned to the index, since the instance + * document can overwrite it by xsi:type. + */ + void setAssignedType(const QXmlNodeModelIndex &index, const SchemaType::Ptr &type); + + /** + * Returns the type that is assigned to the xml node at @p index. + */ + SchemaType::Ptr assignedType(const QXmlNodeModelIndex &index) const; + + /** + * Adds the attribute or element @p binding with the given @p id. + */ + void addIdIdRefBinding(const QString &id, const NamedSchemaComponent::Ptr &binding); + + /** + * Returns a list of all binding ids. + */ + QStringList idIdRefBindingIds() const; + + /** + * Returns the set of bindings with the given @p id. + */ + QSet idIdRefBindings(const QString &id) const; + + protected: + virtual QXmlNodeModelIndex nextFromSimpleAxis(SimpleAxis axis, const QXmlNodeModelIndex &origin) const; + virtual QVector attributes(const QXmlNodeModelIndex &element) const; + + private: + QAbstractXmlNodeModel::Ptr m_internalModel; + QHash m_assignedElements; + QHash m_assignedAttributes; + QHash m_assignedTypes; + QHash > m_idIdRefBindings; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsdvalidatinginstancereader.cpp b/src/xmlpatterns/schema/qxsdvalidatinginstancereader.cpp new file mode 100644 index 0000000..12fc477 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdvalidatinginstancereader.cpp @@ -0,0 +1,1245 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qxsdvalidatinginstancereader_p.h" + +#include "qabstractdatetime_p.h" +#include "qacceltreeresourceloader_p.h" +#include "qbase64binary_p.h" +#include "qboolean_p.h" +#include "qderivedinteger_p.h" +#include "qduration_p.h" +#include "qgenericstaticcontext_p.h" +#include "qhexbinary_p.h" +#include "qnamespaceresolver_p.h" +#include "qpatternplatform_p.h" +#include "qqnamevalue_p.h" +#include "qsourcelocationreflection_p.h" +#include "qvaluefactory_p.h" +#include "qxmlnamepool.h" +#include "qxmlquery_p.h" +#include "qxmlschema_p.h" +#include "qxsdschemahelper_p.h" +#include "qxsdschemamerger_p.h" +#include "qxsdstatemachine_p.h" +#include "qxsdstatemachinebuilder_p.h" +#include "qxsdtypechecker_p.h" + +#include "qxsdschemadebugger_p.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +namespace QPatternist +{ + template <> + template <> + bool XsdStateMachine::inputEqualsTransition(QXmlName name, XsdTerm::Ptr term) const + { + if (term->isElement()) { + return (XsdElement::Ptr(term)->name(m_namePool) == name); + } else if (term->isWildcard()) { + // wildcards using XsdWildcard::absentNamespace, so we have to fix that here + if (name.namespaceURI() == StandardNamespaces::empty) { + name.setNamespaceURI(m_namePool->allocateNamespace(XsdWildcard::absentNamespace())); + } + + return XsdSchemaHelper::wildcardAllowsExpandedName(name, XsdWildcard::Ptr(term), m_namePool); + } + + return false; + } +} + +XsdValidatingInstanceReader::XsdValidatingInstanceReader(const XsdValidatedXmlNodeModel *model, const QUrl &documentUri, const XsdSchemaContext::Ptr &context) + : XsdInstanceReader(model, context) + , m_model(const_cast(model)) + , m_namePool(m_context->namePool()) + , m_xsiNilName(m_namePool->allocateQName(QLatin1String("http://www.w3.org/2001/XMLSchema-instance"), QLatin1String("nil"))) + , m_xsiTypeName(m_namePool->allocateQName(QLatin1String("http://www.w3.org/2001/XMLSchema-instance"), QLatin1String("type"))) + , m_xsiSchemaLocationName(m_namePool->allocateQName(QLatin1String("http://www.w3.org/2001/XMLSchema-instance"), QLatin1String("schemaLocation"))) + , m_xsiNoNamespaceSchemaLocationName(m_namePool->allocateQName(QLatin1String("http://www.w3.org/2001/XMLSchema-instance"), QLatin1String("noNamespaceSchemaLocation"))) + , m_documentUri(documentUri) +{ + m_idRefsType = m_context->schemaTypeFactory()->createSchemaType(m_namePool->allocateQName(CommonNamespaces::WXS, QLatin1String("IDREFS"))); +} + +void XsdValidatingInstanceReader::addSchema(const XsdSchema::Ptr &schema, const QUrl &locationUrl) +{ + if (!m_mergedSchemas.contains(locationUrl)) { + m_mergedSchemas.insert(locationUrl, QStringList() << schema->targetNamespace()); + } else { + QStringList &targetNamespaces = m_mergedSchemas[locationUrl]; + if (targetNamespaces.contains(schema->targetNamespace())) + return; + + targetNamespaces.append(schema->targetNamespace()); + } + + const XsdSchemaMerger merger(m_schema, schema); + m_schema = merger.mergedSchema(); +/* + XsdSchemaDebugger dbg(m_namePool); + dbg.dumpSchema(m_schema); +*/ +} + +bool XsdValidatingInstanceReader::read() +{ + while (!atEnd()) { + readNext(); + + if (isEndElement()) + return true; + + if (isStartElement()) { + const QXmlName elementName = name(); + const QXmlItem currentItem = item(); + bool hasStateMachine = false; + XsdElement::Ptr processedElement; + + if (!validate(hasStateMachine, processedElement)) + return false; + + read(); + + if (processedElement) { // for wildcard with 'skip' we have no element + m_model->setAssignedElement(currentItem.toNodeModelIndex(), processedElement); + + // check identity constraints after all child nodes have been + // validated, so that we know there assigned types + validateIdentityConstraint(processedElement, currentItem); + } + + if (!m_stateMachines.isEmpty() && hasStateMachine) { + if (!m_stateMachines.top().inEndState()) { + error(QtXmlPatterns::tr("element %1 is missing child element").arg(formatKeyword(m_namePool->displayName(elementName)))); + return false; + } + m_stateMachines.pop(); + } + } + } + + // final validations + + // check IDREF occurrences + const QStringList ids = m_model->idIdRefBindingIds(); + QSetIterator it(m_idRefs); + while (it.hasNext()) { + const QString id = it.next(); + if (!ids.contains(id)) { + error(QtXmlPatterns::tr("there is one IDREF value with no corresponding ID: %1").arg(formatKeyword(id))); + return false; + } + } + + return true; +} + +void XsdValidatingInstanceReader::error(const QString &msg) const +{ + const_cast(m_context.data())->error(msg, XsdSchemaContext::XSDError, sourceLocation()); +} + +bool XsdValidatingInstanceReader::loadSchema(const QString &targetNamespace, const QUrl &location) +{ + const AutoPtr reply(AccelTreeResourceLoader::load(location, m_context->networkAccessManager(), + m_context, AccelTreeResourceLoader::ContinueOnError)); + if (!reply) + return true; + + // we have to create a separated schema context here, that however shares the type factory + XsdSchemaContext::Ptr context(new XsdSchemaContext(m_namePool)); + context->m_schemaTypeFactory = m_context->m_schemaTypeFactory; + + QXmlSchemaPrivate schema(context); + schema.load(reply.data(), location, targetNamespace); + if (!schema.isValid()) { + error(QtXmlPatterns::tr("loaded schema file is invalid")); + return false; + } + + addSchema(schema.m_schemaParserContext->schema(), location); + + return true; +} + +bool XsdValidatingInstanceReader::validate(bool &hasStateMachine, XsdElement::Ptr &processedElement) +{ + // first check if a custom schema is defined + if (hasAttribute(m_xsiSchemaLocationName)) { + const QString schemaLocation = attribute(m_xsiSchemaLocationName); + const QStringList parts = schemaLocation.split(QLatin1Char(' '), QString::SkipEmptyParts); + if ((parts.count()%2) == 1) { + error(QtXmlPatterns::tr("%1 contains invalid data").arg(formatKeyword(m_namePool, m_xsiSchemaLocationName))); + return false; + } + + for (int i = 0; i < parts.count(); i += 2) { + const QString identifier = QString::fromLatin1("%1 %2").arg(parts.at(i)).arg(parts.at(i + 1)); + if (m_processedSchemaLocations.contains(identifier)) + continue; + else + m_processedSchemaLocations.insert(identifier); + + // check constraint 4) from http://www.w3.org/TR/xmlschema-1/#schema-loc (only valid for XML Schema 1.0?) + if (m_processedNamespaces.contains(parts.at(i))) { + error(QtXmlPatterns::tr("xsi:schemaLocation namespace %1 has already appeared earlier in the instance document").arg(formatKeyword(parts.at(i)))); + return false; + } + + QUrl url(parts.at(i + 1)); + if (url.isRelative()) { + Q_ASSERT(m_documentUri.isValid()); + + url = m_documentUri.resolved(url); + } + + loadSchema(parts.at(i), url); + } + } + + if (hasAttribute(m_xsiNoNamespaceSchemaLocationName)) { + const QString schemaLocation = attribute(m_xsiNoNamespaceSchemaLocationName); + + if (!m_processedSchemaLocations.contains(schemaLocation)) { + m_processedSchemaLocations.insert(schemaLocation); + + if (m_processedNamespaces.contains(QString())) { + error(QtXmlPatterns::tr("xsi:noNamespaceSchemaLocation cannot appear after the first no-namespace element or attribute")); + return false; + } + + QUrl url(schemaLocation); + if (url.isRelative()) { + Q_ASSERT(m_documentUri.isValid()); + + url = m_documentUri.resolved(url); + } + + loadSchema(QString(), url); + } + } + + m_processedNamespaces.insert(m_namePool->stringForNamespace(name().namespaceURI())); + + if (!m_schema) { + error(QtXmlPatterns::tr("no schema defined for validation")); + return false; + } + + // check if we are 'inside' a type definition + if (m_stateMachines.isEmpty()) { + // find out the type of the top-level element + XsdElement::Ptr element = elementByName(name()); + if (!element) { + if (!hasAttribute(m_xsiTypeName)) { + error(QtXmlPatterns::tr("no definition for element %1 available").arg(formatKeyword(m_namePool, name()))); + return false; + } + + // This instance document has an element with no definition in the schema + // but an explicitly given type, that is fine according to the spec. + // We will create an element definition manually here and continue the + // normal validation process + element = XsdElement::Ptr(new XsdElement()); + element->setName(name()); + element->setIsAbstract(false); + element->setIsNillable(hasAttribute(m_xsiNilName)); + + const QString type = qNameAttribute(m_xsiTypeName); + const QXmlName typeName = convertToQName(type); + + const SchemaType::Ptr elementType = typeByName(typeName); + if (!elementType) { + error(QtXmlPatterns::tr("specified type %1 is not known to the schema").arg(formatType(m_namePool, typeName))); + return false; + } + element->setType(elementType); + } + + // rememeber the element we process + processedElement = element; + + if (!validateElement(element, hasStateMachine)) { + return false; + } + + } else { + if (!m_stateMachines.top().proceed(name())) { + error(QtXmlPatterns::tr("element %1 is not defined in this scope").arg(formatKeyword(m_namePool, name()))); + return false; + } + + const XsdTerm::Ptr term = m_stateMachines.top().lastTransition(); + if (term->isElement()) { + const XsdElement::Ptr element(term); + + // rememeber the element we process + processedElement = element; + + if (!validateElement(element, hasStateMachine)) + return false; + + } else { + const XsdWildcard::Ptr wildcard(term); + if (wildcard->processContents() != XsdWildcard::Skip) { + XsdElement::Ptr elementDeclaration = elementByName(name()); + if (!elementDeclaration) { + if (hasAttribute(m_xsiTypeName)) { + // This instance document has an element with no definition in the schema + // but an explicitly given type, that is fine according to the spec. + // We will create an element definition manually here and continue the + // normal validation process + elementDeclaration = XsdElement::Ptr(new XsdElement()); + elementDeclaration->setName(name()); + elementDeclaration->setIsAbstract(false); + elementDeclaration->setIsNillable(hasAttribute(m_xsiNilName)); + + const QString type = qNameAttribute(m_xsiTypeName); + const QXmlName typeName = convertToQName(type); + + const SchemaType::Ptr elementType = typeByName(typeName); + if (!elementType) { + error(QtXmlPatterns::tr("specified type %1 is not known to the schema").arg(formatType(m_namePool, typeName))); + return false; + } + elementDeclaration->setType(elementType); + } + } + + if (!elementDeclaration) { + if (wildcard->processContents() == XsdWildcard::Strict) { + error(QtXmlPatterns::tr("declaration for element %1 does not exist").arg(formatKeyword(m_namePool->displayName(name())))); + return false; + } else { + // in this case we put a state machine for the xs:anyType on the statemachine stack, + // so we accept every content of this element + + createAndPushStateMachine(anyType()->contentType()->particle()); + hasStateMachine = true; + } + } else { + if (!validateElement(elementDeclaration, hasStateMachine)) { + if (wildcard->processContents() == XsdWildcard::Strict) { + error(QtXmlPatterns::tr("element %1 contains invalid content").arg(formatKeyword(m_namePool->displayName(name())))); + return false; + } + } + + // rememeber the type of that element node + m_model->setAssignedType(item().toNodeModelIndex(), elementDeclaration->type()); + } + } else { // wildcard process contents type is Skip + // in this case we put a state machine for the xs:anyType on the statemachine stack, + // so we accept every content of this element + + const XsdWildcard::Ptr wildcard(new XsdWildcard()); + wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Any); + wildcard->setProcessContents(XsdWildcard::Skip); + + const XsdParticle::Ptr outerParticle(new XsdParticle()); + outerParticle->setMinimumOccurs(1); + outerParticle->setMaximumOccurs(1); + + const XsdParticle::Ptr innerParticle(new XsdParticle()); + innerParticle->setMinimumOccurs(0); + innerParticle->setMaximumOccursUnbounded(true); + innerParticle->setTerm(wildcard); + + const XsdModelGroup::Ptr outerModelGroup(new XsdModelGroup()); + outerModelGroup->setCompositor(XsdModelGroup::SequenceCompositor); + outerModelGroup->setParticles(XsdParticle::List() << innerParticle); + outerParticle->setTerm(outerModelGroup); + + createAndPushStateMachine(outerParticle); + hasStateMachine = true; + } + } + } + + return true; +} + +void XsdValidatingInstanceReader::createAndPushStateMachine(const XsdParticle::Ptr &particle) +{ + XsdStateMachine stateMachine(m_namePool); + + XsdStateMachineBuilder builder(&stateMachine, m_namePool, XsdStateMachineBuilder::ValidatingMode); + const XsdStateMachine::StateId endState = builder.reset(); + const XsdStateMachine::StateId startState = builder.buildParticle(particle, endState); + builder.addStartState(startState); + +/* + QString fileName = QString("/tmp/foo_%1.dot").arg(m_namePool->displayName(complexType->name(m_namePool))); + QString pngFileName = QString("/tmp/foo_%1.png").arg(m_namePool->displayName(complexType->name(m_namePool))); + QFile file(fileName); + file.open(QIODevice::WriteOnly); + stateMachine.outputGraph(&file, "Hello"); + file.close(); + ::system(QString("dot -Tpng %1 -o%2").arg(fileName).arg(pngFileName).toLatin1().data()); +*/ + + stateMachine = stateMachine.toDFA(); + + m_stateMachines.push(stateMachine); +} + +bool XsdValidatingInstanceReader::validateElement(const XsdElement::Ptr &declaration, bool &hasStateMachine) +{ + // http://www.w3.org/TR/xmlschema11-1/#d0e10998 + + bool isNilled = false; + + // 1 tested already, 'declaration' corresponds D + + // 2 + if (declaration->isAbstract()) { + error(QtXmlPatterns::tr("element %1 is declared as abstract").arg(formatKeyword(declaration->displayName(m_namePool)))); + return false; + } + + // 3 + if (!declaration->isNillable()) { + if (hasAttribute(m_xsiNilName)) { + error(QtXmlPatterns::tr("element %1 is not nillable").arg(formatKeyword(declaration->displayName(m_namePool)))); + return false; // 3.1 + } + } else { + if (hasAttribute(m_xsiNilName)) { + const QString value = attribute(m_xsiNilName); + const Boolean::Ptr nil = Boolean::fromLexical(value); + if (nil->hasError()) { + error(QtXmlPatterns::tr("attribute %1 contains invalid data: %1").arg(formatKeyword(QLatin1String("nil"))).arg(formatData(value))); + return false; + } + + // 3.2.3 + if (nil->as()->value() == true) { + // 3.2.3.1 + if (hasChildElement() || hasChildText()) { + error(QtXmlPatterns::tr("element contains content although it is nillable")); + return false; + } + + // 3.2.3.2 + if (declaration->valueConstraint() && declaration->valueConstraint()->variety() == XsdElement::ValueConstraint::Fixed) { + error(QtXmlPatterns::tr("fixed value constrained not allowed if element is nillable")); + return false; + } + } + + isNilled = nil->as()->value(); + } + } + + SchemaType::Ptr finalElementType = declaration->type(); + + // 4 + if (hasAttribute(m_xsiTypeName)) { + const QString type = qNameAttribute(m_xsiTypeName); + const QXmlName typeName = convertToQName(type); + + const SchemaType::Ptr elementType = typeByName(typeName); + // 4.1 + if (!elementType) { + error(QtXmlPatterns::tr("specified type %1 is not known to the schema").arg(formatType(m_namePool, typeName))); + return false; + } + + // 4.2 + SchemaType::DerivationConstraints constraints = 0; + if (declaration->disallowedSubstitutions() & NamedSchemaComponent::ExtensionConstraint) + constraints |= SchemaType::ExtensionConstraint; + if (declaration->disallowedSubstitutions() & NamedSchemaComponent::RestrictionConstraint) + constraints |= SchemaType::RestrictionConstraint; + + if (!XsdSchemaHelper::isValidlySubstitutable(elementType, declaration->type(), constraints)) { + if (declaration->type()->name(m_namePool) != BuiltinTypes::xsAnyType->name(m_namePool)) { // xs:anyType is a valid substitutable type here + error(QtXmlPatterns::tr("specified type %1 is not validly substitutable with element type %2").arg(formatType(m_namePool, elementType)).arg(formatType(m_namePool, declaration->type()))); + return false; + } + } + + finalElementType = elementType; + } + + if (!validateElementType(declaration, finalElementType, isNilled, hasStateMachine)) + return false; + + return true; +} + +bool XsdValidatingInstanceReader::validateElementType(const XsdElement::Ptr &declaration, const SchemaType::Ptr &type, bool isNilled, bool &hasStateMachine) +{ + // @see http://www.w3.org/TR/xmlschema11-1/#d0e11749 + + // 1 checked already + + // 2 + if (type->isComplexType() && type->isDefinedBySchema()) { + if (XsdComplexType::Ptr(type)->isAbstract()) { + error(QtXmlPatterns::tr("complex type %1 is not allowed to be abstract").arg(formatType(m_namePool, type))); + return false; + } + } + + // 3 + if (type->isSimpleType()) + return validateElementSimpleType(declaration, type, isNilled); // 3.1 + else + return validateElementComplexType(declaration, type, isNilled, hasStateMachine); // 3.2 +} + +bool XsdValidatingInstanceReader::validateElementSimpleType(const XsdElement::Ptr &declaration, const SchemaType::Ptr &type, bool isNilled) +{ + // @see http://www.w3.org/TR/xmlschema11-1/#d0e11749 + + // 3.1.1 + const QSet allowedAttributes(QSet() << m_xsiNilName << m_xsiTypeName << m_xsiSchemaLocationName << m_xsiNoNamespaceSchemaLocationName); + QSet elementAttributes = attributeNames(); + elementAttributes.subtract(allowedAttributes); + if (!elementAttributes.isEmpty()) { + error(QtXmlPatterns::tr("element %1 contains not allowed attributes").arg(formatKeyword(declaration->displayName(m_namePool)))); + return false; + } + + // 3.1.2 + if (hasChildElement()) { + error(QtXmlPatterns::tr("element %1 contains not allowed child element").arg(formatKeyword(declaration->displayName(m_namePool)))); + return false; + } + + // 3.1.3 + if (!isNilled) { + const XsdFacet::Hash facets = XsdTypeChecker::mergedFacetsForType(type, m_context); + + QString actualValue; + if (hasChildText()) { + actualValue = XsdTypeChecker::normalizedValue(text(), facets); + } else { + if (declaration->valueConstraint()) + actualValue = XsdTypeChecker::normalizedValue(declaration->valueConstraint()->value(), facets); + } + + QString errorMsg; + AnySimpleType::Ptr boundType; + + const XsdTypeChecker checker(m_context, namespaceBindings(item().toNodeModelIndex()), sourceLocation()); + if (!checker.isValidString(actualValue, type, errorMsg, &boundType)) { + error(QtXmlPatterns::tr("content of element %1 does not match its type definition: %2").arg(formatKeyword(declaration->displayName(m_namePool))).arg(errorMsg)); + return false; + } + + // additional check + if (declaration->valueConstraint() && declaration->valueConstraint()->variety() == XsdElement::ValueConstraint::Fixed) { + const QString actualConstraintValue = XsdTypeChecker::normalizedValue(declaration->valueConstraint()->value(), facets); + if (!text().isEmpty() && !checker.valuesAreEqual(actualValue, actualConstraintValue, type)) { + error(QtXmlPatterns::tr("content of element %1 does not match defined value constraint").arg(formatKeyword(declaration->displayName(m_namePool)))); + return false; + } + } + } + + // 4 checked in validateElement already + + // rememeber the type of that element node + m_model->setAssignedType(item().toNodeModelIndex(), type); + + const XsdFacet::Hash facets = XsdTypeChecker::mergedFacetsForType(type, m_context); + const QString actualValue = XsdTypeChecker::normalizedValue(text(), facets); + + if (BuiltinTypes::xsID->wxsTypeMatches(type)) { + addIdIdRefBinding(actualValue, declaration); + } + + if (m_idRefsType->wxsTypeMatches(type)) { + const QStringList idRefs = actualValue.split(QLatin1Char(' '), QString::SkipEmptyParts); + for (int i = 0; i < idRefs.count(); ++i) { + m_idRefs.insert(idRefs.at(i)); + } + } else if (BuiltinTypes::xsIDREF->wxsTypeMatches(type)) { + m_idRefs.insert(actualValue); + } + + return true; +} + +static bool hasIDAttributeUse(const XsdAttributeUse::List &uses) +{ + const int count = uses.count(); + for (int i = 0; i < count; ++i) { + if (BuiltinTypes::xsID->wxsTypeMatches(uses.at(i)->attribute()->type())) + return true; + } + + return false; +} + +bool XsdValidatingInstanceReader::validateElementComplexType(const XsdElement::Ptr &declaration, const SchemaType::Ptr &type, bool isNilled, bool &hasStateMachine) +{ + // @see http://www.w3.org/TR/xmlschema11-1/#cvc-complex-type + + // 1 + if (!isNilled) { + XsdComplexType::Ptr complexType; + + if (type->isDefinedBySchema()) { + complexType = XsdComplexType::Ptr(type); + } else { + if (type->name(m_namePool) == BuiltinTypes::xsAnyType->name(m_namePool)) + complexType = anyType(); + } + + if (complexType) { + // 1.1 + if (complexType->contentType()->variety() == XsdComplexType::ContentType::Empty) { + if (hasChildText() || hasChildElement()) { + error(QtXmlPatterns::tr("element %1 contains not allowed child content").arg(formatKeyword(declaration->displayName(m_namePool)))); + return false; + } + } + + // 1.2 + if (complexType->contentType()->variety() == XsdComplexType::ContentType::Simple) { + if (hasChildElement()) { + error(QtXmlPatterns::tr("element %1 contains not allowed child element").arg(formatKeyword(declaration->displayName(m_namePool)))); + return false; + } + + const XsdFacet::Hash facets = XsdTypeChecker::mergedFacetsForType(complexType->contentType()->simpleType(), m_context); + QString actualValue; + if (hasChildText()) { + actualValue = XsdTypeChecker::normalizedValue(text(), facets); + } else { + if (declaration->valueConstraint()) + actualValue = XsdTypeChecker::normalizedValue(declaration->valueConstraint()->value(), facets); + } + + QString errorMsg; + AnySimpleType::Ptr boundType; + const XsdTypeChecker checker(m_context, namespaceBindings(item().toNodeModelIndex()), sourceLocation()); + if (!checker.isValidString(actualValue, complexType->contentType()->simpleType(), errorMsg, &boundType)) { + error(QtXmlPatterns::tr("content of element %1 does not match its type definition: %2").arg(formatKeyword(declaration->displayName(m_namePool))).arg(errorMsg)); + return false; + } + + // additional check + if (declaration->valueConstraint() && declaration->valueConstraint()->variety() == XsdElement::ValueConstraint::Fixed) { + if (!checker.valuesAreEqual(actualValue, declaration->valueConstraint()->value(), boundType)) { + error(QtXmlPatterns::tr("content of element %1 does not match defined value constraint").arg(formatKeyword(declaration->displayName(m_namePool)))); + return false; + } + } + } + + // 1.3 + if (complexType->contentType()->variety() == XsdComplexType::ContentType::ElementOnly) { + if (!text().simplified().isEmpty()) { + error(QtXmlPatterns::tr("element %1 contains not allowed text content").arg(formatKeyword(declaration->displayName(m_namePool)))); + return false; + } + } + + // 1.4 + if (complexType->contentType()->variety() == XsdComplexType::ContentType::ElementOnly || + complexType->contentType()->variety() == XsdComplexType::ContentType::Mixed) { + + if (complexType->contentType()->particle()) { + createAndPushStateMachine(complexType->contentType()->particle()); + hasStateMachine = true; + } + + // additional check + if (complexType->contentType()->variety() == XsdComplexType::ContentType::Mixed) { + if (declaration->valueConstraint() && declaration->valueConstraint()->variety() == XsdElement::ValueConstraint::Fixed) { + if (hasChildElement()) { + error(QtXmlPatterns::tr("element %1 can not contain other elements, as it has a fixed content").arg(formatKeyword(declaration->displayName(m_namePool)))); + return false; + } + + const XsdFacet::Hash facets = XsdTypeChecker::mergedFacetsForType(complexType->contentType()->simpleType(), m_context); + QString actualValue; + if (hasChildText()) { + actualValue = XsdTypeChecker::normalizedValue(text(), facets); + } else { + if (declaration->valueConstraint()) + actualValue = XsdTypeChecker::normalizedValue(declaration->valueConstraint()->value(), facets); + } + + if (actualValue != declaration->valueConstraint()->value()) { + error(QtXmlPatterns::tr("content of element %1 does not match defined value constraint").arg(formatKeyword(declaration->displayName(m_namePool)))); + return false; + } + } + } + } + } + } + + if (type->isDefinedBySchema()) { + const XsdComplexType::Ptr complexType(type); + + // create a lookup hash for faster access + QHash attributeUseHash; + { + const XsdAttributeUse::List attributeUses = complexType->attributeUses(); + for (int i = 0; i < attributeUses.count(); ++i) + attributeUseHash.insert(attributeUses.at(i)->attribute()->name(m_namePool), attributeUses.at(i)); + } + + const QSet attributes(attributeNames()); + + // 3 + QHashIterator usesIt(attributeUseHash); + while (usesIt.hasNext()) { + usesIt.next(); + + if (usesIt.value()->isRequired()) { + if (!attributes.contains(usesIt.key())) { + error(QtXmlPatterns::tr("element %1 is missing required attribute %2").arg(formatKeyword(declaration->displayName(m_namePool))) + .arg(formatKeyword(m_namePool->displayName(usesIt.key())))); + return false; + } + } + } + + bool hasIDAttribute = hasIDAttributeUse(complexType->attributeUses()); + + // 2 + QSetIterator it(attributes); + while (it.hasNext()) { + const QXmlName attributeName = it.next(); + + // skip builtin attributes + if (attributeName == m_xsiNilName || + attributeName == m_xsiTypeName || + attributeName == m_xsiSchemaLocationName || + attributeName == m_xsiNoNamespaceSchemaLocationName) + continue; + + // 2.1 + if (attributeUseHash.contains(attributeName) && (attributeUseHash.value(attributeName)->useType() != XsdAttributeUse::ProhibitedUse)) { + if (!validateAttribute(attributeUseHash.value(attributeName), attribute(attributeName))) + return false; + } else { // 2.2 + if (complexType->attributeWildcard()) { + const XsdWildcard::Ptr wildcard(complexType->attributeWildcard()); + if (!validateAttributeWildcard(attributeName, wildcard)) { + error(QtXmlPatterns::tr("attribute %1 does not match the attribute wildcard").arg(formatKeyword(m_namePool->displayName(attributeName)))); + return false; + } + + if (wildcard->processContents() != XsdWildcard::Skip) { + const XsdAttribute::Ptr attributeDeclaration = attributeByName(attributeName); + + if (!attributeDeclaration) { + if (wildcard->processContents() == XsdWildcard::Strict) { + error(QtXmlPatterns::tr("declaration for attribute %1 does not exist").arg(formatKeyword(m_namePool->displayName(attributeName)))); + return false; + } + } else { + if (BuiltinTypes::xsID->wxsTypeMatches(attributeDeclaration->type())) { + if (hasIDAttribute) { + error(QtXmlPatterns::tr("element %1 contains two attributes of type %2") + .arg(formatKeyword(declaration->displayName(m_namePool))) + .arg(formatKeyword("ID"))); + return false; + } + + hasIDAttribute = true; + } + + if (!validateAttribute(attributeDeclaration, attribute(attributeName))) { + if (wildcard->processContents() == XsdWildcard::Strict) { + error(QtXmlPatterns::tr("attribute %1 contains invalid content").arg(formatKeyword(m_namePool->displayName(attributeName)))); + return false; + } + } + } + } + } else { + error(QtXmlPatterns::tr("element %1 contains unknown attribute %2").arg(formatKeyword(declaration->displayName(m_namePool))) + .arg(formatKeyword(m_namePool->displayName(attributeName)))); + return false; + } + } + } + } + + // 4 + // so what?... + + // 5 + // hmm... + + // 6 + // TODO: check assertions + + // 7 + // TODO: check type table restrictions + + // rememeber the type of that element node + m_model->setAssignedType(item().toNodeModelIndex(), type); + + return true; +} + +bool XsdValidatingInstanceReader::validateAttribute(const XsdAttributeUse::Ptr &declaration, const QString &value) +{ + const AnySimpleType::Ptr attributeType = declaration->attribute()->type(); + const XsdFacet::Hash facets = XsdTypeChecker::mergedFacetsForType(attributeType, m_context); + + const QString actualValue = XsdTypeChecker::normalizedValue(value, facets); + + QString errorMsg; + AnySimpleType::Ptr boundType; + + const QXmlNodeModelIndex index = attributeItem(declaration->attribute()->name(m_namePool)).toNodeModelIndex(); + + const XsdTypeChecker checker(m_context, namespaceBindings(index), sourceLocation()); + if (!checker.isValidString(actualValue, attributeType, errorMsg, &boundType)) { + error(QtXmlPatterns::tr("content of attribute %1 does not match its type definition: %2").arg(formatKeyword(declaration->attribute()->displayName(m_namePool))).arg(errorMsg)); + return false; + } + + // @see http://www.w3.org/TR/xmlschema11-1/#cvc-au + if (declaration->valueConstraint() && declaration->valueConstraint()->variety() == XsdAttributeUse::ValueConstraint::Fixed) { + const QString actualConstraintValue = XsdTypeChecker::normalizedValue(declaration->valueConstraint()->value(), facets); + if (!checker.valuesAreEqual(actualValue, actualConstraintValue, attributeType)) { + error(QtXmlPatterns::tr("content of attribute %1 does not match defined value constraint").arg(formatKeyword(declaration->attribute()->displayName(m_namePool)))); + return false; + } + } + + if (BuiltinTypes::xsID->wxsTypeMatches(declaration->attribute()->type())) { + addIdIdRefBinding(actualValue, declaration->attribute()); + } + + if (m_idRefsType->wxsTypeMatches(declaration->attribute()->type())) { + const QStringList idRefs = actualValue.split(QLatin1Char(' '), QString::SkipEmptyParts); + for (int i = 0; i < idRefs.count(); ++i) + m_idRefs.insert(idRefs.at(i)); + } else if (BuiltinTypes::xsIDREF->wxsTypeMatches(declaration->attribute()->type())) { + m_idRefs.insert(actualValue); + } + + m_model->setAssignedType(index, declaration->attribute()->type()); + m_model->setAssignedAttribute(index, declaration->attribute()); + + return true; +} + +//TODO: merge that with the method above +bool XsdValidatingInstanceReader::validateAttribute(const XsdAttribute::Ptr &declaration, const QString &value) +{ + const AnySimpleType::Ptr attributeType = declaration->type(); + const XsdFacet::Hash facets = XsdTypeChecker::mergedFacetsForType(attributeType, m_context); + + const QString actualValue = XsdTypeChecker::normalizedValue(value, facets); + + QString errorMsg; + AnySimpleType::Ptr boundType; + + const QXmlNodeModelIndex index = attributeItem(declaration->name(m_namePool)).toNodeModelIndex(); + + const XsdTypeChecker checker(m_context, namespaceBindings(index), sourceLocation()); + if (!checker.isValidString(actualValue, attributeType, errorMsg, &boundType)) { + error(QtXmlPatterns::tr("content of attribute %1 does not match its type definition: %2").arg(formatKeyword(declaration->displayName(m_namePool))).arg(errorMsg)); + return false; + } + + // @see http://www.w3.org/TR/xmlschema11-1/#cvc-au + if (declaration->valueConstraint() && declaration->valueConstraint()->variety() == XsdAttribute::ValueConstraint::Fixed) { + const QString actualConstraintValue = XsdTypeChecker::normalizedValue(declaration->valueConstraint()->value(), facets); + if (!checker.valuesAreEqual(actualValue, actualConstraintValue, attributeType)) { + error(QtXmlPatterns::tr("content of attribute %1 does not match defined value constraint").arg(formatKeyword(declaration->displayName(m_namePool)))); + return false; + } + } + + if (BuiltinTypes::xsID->wxsTypeMatches(declaration->type())) { + addIdIdRefBinding(actualValue, declaration); + } + + if (m_idRefsType->wxsTypeMatches(declaration->type())) { + const QStringList idRefs = actualValue.split(QLatin1Char(' '), QString::SkipEmptyParts); + for (int i = 0; i < idRefs.count(); ++i) + m_idRefs.insert(idRefs.at(i)); + } else if (BuiltinTypes::xsIDREF->wxsTypeMatches(declaration->type())) { + m_idRefs.insert(actualValue); + } + + m_model->setAssignedType(index, declaration->type()); + m_model->setAssignedAttribute(index, declaration); + + return true; +} + +bool XsdValidatingInstanceReader::validateAttributeWildcard(const QXmlName &attributeName, const XsdWildcard::Ptr &wildcard) +{ + // @see http://www.w3.org/TR/xmlschema11-1/#cvc-wildcard + + // wildcards using XsdWildcard::absentNamespace, so we have to fix that here + QXmlName name(attributeName); + if (name.namespaceURI() == StandardNamespaces::empty) { + name.setNamespaceURI(m_namePool->allocateNamespace(XsdWildcard::absentNamespace())); + } + + return XsdSchemaHelper::wildcardAllowsExpandedName(name, wildcard, m_namePool); +} + +bool XsdValidatingInstanceReader::validateIdentityConstraint(const XsdElement::Ptr &element, const QXmlItem ¤tItem) +{ + const XsdIdentityConstraint::List constraints = element->identityConstraints(); + + for (int i = 0; i < constraints.count(); ++i) { + const XsdIdentityConstraint::Ptr constraint = constraints.at(i); + + TargetNode::Set targetNodeSet, qualifiedNodeSet; + selectNodeSets(element, currentItem, constraint, targetNodeSet, qualifiedNodeSet); + + if (constraint->category() == XsdIdentityConstraint::Unique) { + if (!validateUniqueIdentityConstraint(element, constraint, qualifiedNodeSet)) + return false; + } else if (constraint->category() == XsdIdentityConstraint::Key) { + if (!validateKeyIdentityConstraint(element, constraint, targetNodeSet, qualifiedNodeSet)) + return false; + } + } + + // we do the keyref check in a separated run to make sure that all keys are available + for (int i = 0; i < constraints.count(); ++i) { + const XsdIdentityConstraint::Ptr constraint = constraints.at(i); + if (constraint->category() == XsdIdentityConstraint::KeyReference) { + TargetNode::Set targetNodeSet, qualifiedNodeSet; + selectNodeSets(element, currentItem, constraint, targetNodeSet, qualifiedNodeSet); + + if (!validateKeyRefIdentityConstraint(element, constraint, qualifiedNodeSet)) + return false; + } + } + + return true; +} + +bool XsdValidatingInstanceReader::validateUniqueIdentityConstraint(const XsdElement::Ptr&, const XsdIdentityConstraint::Ptr &constraint, const TargetNode::Set &qualifiedNodeSet) +{ + // @see http://www.w3.org/TR/xmlschema11-1/#d0e32243 + + // 4.1 + const XsdSchemaSourceLocationReflection reflection(sourceLocation()); + + QSetIterator it(qualifiedNodeSet); + while (it.hasNext()) { + const TargetNode node = it.next(); + QSetIterator innerIt(qualifiedNodeSet); + while (innerIt.hasNext()) { + const TargetNode innerNode = innerIt.next(); + + if (node == innerNode) // do not compare with ourself + continue; + + if (node.fieldsAreEqual(innerNode, m_namePool, m_context, &reflection)) { + error(QtXmlPatterns::tr("non-unique value found for constraint %1").arg(formatKeyword(constraint->displayName(m_namePool)))); + return false; + } + } + } + + m_idcKeys.insert(constraint->name(m_namePool), qualifiedNodeSet); + + return true; +} + +bool XsdValidatingInstanceReader::validateKeyIdentityConstraint(const XsdElement::Ptr &element, const XsdIdentityConstraint::Ptr &constraint, const TargetNode::Set &targetNodeSet, const TargetNode::Set &qualifiedNodeSet) +{ + // @see http://www.w3.org/TR/xmlschema11-1/#d0e32243 + + // 4.2 + const XsdSchemaSourceLocationReflection reflection(sourceLocation()); + + // 4.2.1 + if (targetNodeSet.count() != qualifiedNodeSet.count()) { + error(QtXmlPatterns::tr("key constraint %1 contains absent fields").arg(formatKeyword(constraint->displayName(m_namePool)))); + return false; + } + + // 4.2.2 + if (!validateUniqueIdentityConstraint(element, constraint, qualifiedNodeSet)) + return false; + + // 4.2.3 + QSetIterator it(qualifiedNodeSet); + while (it.hasNext()) { + const TargetNode node = it.next(); + const QVector fieldItems = node.fieldItems(); + for (int i = 0; i < fieldItems.count(); ++i) { + const QXmlNodeModelIndex index = fieldItems.at(i).toNodeModelIndex(); + if (m_model->kind(index) == QXmlNodeModelIndex::Element) { + const XsdElement::Ptr declaration = m_model->assignedElement(index); + if (declaration && declaration->isNillable()) { + error(QtXmlPatterns::tr("key constraint %1 contains references nillable element %2") + .arg(formatKeyword(constraint->displayName(m_namePool))) + .arg(formatKeyword(declaration->displayName(m_namePool)))); + return false; + } + } + } + } + + m_idcKeys.insert(constraint->name(m_namePool), qualifiedNodeSet); + + return true; +} + +bool XsdValidatingInstanceReader::validateKeyRefIdentityConstraint(const XsdElement::Ptr&, const XsdIdentityConstraint::Ptr &constraint, const TargetNode::Set &qualifiedNodeSet) +{ + // @see http://www.w3.org/TR/xmlschema11-1/#d0e32243 + + // 4.3 + const XsdSchemaSourceLocationReflection reflection(sourceLocation()); + + const TargetNode::Set keySet = m_idcKeys.value(constraint->referencedKey()->name(m_namePool)); + + QSetIterator it(qualifiedNodeSet); + while (it.hasNext()) { + const TargetNode node = it.next(); + + bool foundMatching = false; + + QSetIterator keyIt(keySet); + while (keyIt.hasNext()) { + const TargetNode keyNode = keyIt.next(); + + if (node.fieldsAreEqual(keyNode, m_namePool, m_context, &reflection)) { + foundMatching = true; + break; + } + } + + if (!foundMatching) { + error(QtXmlPatterns::tr("no referenced value found for key reference %1").arg(formatKeyword(constraint->displayName(m_namePool)))); + return false; + } + } + + return true; +} + +QXmlQuery XsdValidatingInstanceReader::createXQuery(const QList &namespaceBindings, const QXmlItem &contextNode, const QString &queryString) const +{ + // create a public name pool from our name pool + QXmlNamePool namePool(m_namePool.data()); + + // the QXmlQuery shall work with the same name pool as we do + QXmlQuery query(namePool); + + // add additional namespace bindings + QXmlQueryPrivate *queryPrivate = query.d; + + for (int i = 0; i < namespaceBindings.count(); ++i) { + if (!namespaceBindings.at(i).prefix() == StandardPrefixes::empty) + queryPrivate->addAdditionalNamespaceBinding(namespaceBindings.at(i)); + } + + // set the context node for that query and the query string + query.setFocus(contextNode); + query.setQuery(queryString, m_documentUri); + + return query; +} + +bool XsdValidatingInstanceReader::selectNodeSets(const XsdElement::Ptr&, const QXmlItem ¤tItem, const XsdIdentityConstraint::Ptr &constraint, TargetNode::Set &targetNodeSet, TargetNode::Set &qualifiedNodeSet) +{ + // at first select all target nodes + const XsdXPathExpression::Ptr selector = constraint->selector(); + const XsdXPathExpression::List fields = constraint->fields(); + + QXmlQuery query = createXQuery(selector->namespaceBindings(), currentItem, selector->expression()); + + QXmlResultItems resultItems; + query.evaluateTo(&resultItems); + + // now we iterate over all target nodes and select the fields for each node + QXmlItem item(resultItems.next()); + while (!item.isNull()) { + + TargetNode targetNode(item); + + for (int i = 0; i < fields.count(); ++i) { + const XsdXPathExpression::Ptr field = fields.at(i); + QXmlQuery fieldQuery = createXQuery(field->namespaceBindings(), item, field->expression()); + + QXmlResultItems fieldResultItems; + fieldQuery.evaluateTo(&fieldResultItems); + + // copy result into vetor for better testing... + QVector fieldVector; + QXmlItem fieldItem(fieldResultItems.next()); + while (!fieldItem.isNull()) { + fieldVector.append(fieldItem); + fieldItem = fieldResultItems.next(); + } + + if (fieldVector.count() > 1) { + error(QtXmlPatterns::tr("more than one value found for field %1").arg(formatData(field->expression()))); + return false; + } + + if (fieldVector.count() == 1) { + fieldItem = fieldVector.first(); + + const QXmlNodeModelIndex index = fieldItem.toNodeModelIndex(); + const SchemaType::Ptr type = m_model->assignedType(index); + + bool typeOk = true; + if (type->isComplexType()) { + if (type->isDefinedBySchema()) { + if (XsdComplexType::Ptr(type)->contentType()->variety() != XsdComplexType::ContentType::Simple) + typeOk = false; + } else { + typeOk = false; + } + } + if (!typeOk) { + error(QtXmlPatterns::tr("field %1 has no simple type").arg(formatData(field->expression()))); + return false; + } + + SchemaType::Ptr targetType = type; + QString value = m_model->stringValue(fieldItem.toNodeModelIndex()); + + if (type->isDefinedBySchema()) { + if (type->isSimpleType()) + targetType = XsdSimpleType::Ptr(type)->primitiveType(); + else + targetType = XsdComplexType::Ptr(type)->contentType()->simpleType(); + } else { + if (BuiltinTypes::xsAnySimpleType->name(m_namePool) == type->name(m_namePool)) { + targetType = BuiltinTypes::xsString; + value = QLatin1String("___anySimpleType_value"); + } + } + + // if it is xs:QName derived type, we normalize the name content + // and do a string comparison + if (BuiltinTypes::xsQName->wxsTypeMatches(type)) { + targetType = BuiltinTypes::xsString; + + const QXmlName qName = convertToQName(value.trimmed()); + value = QString::fromLatin1("%1:%2").arg(m_namePool->stringForNamespace(qName.namespaceURI())).arg(m_namePool->stringForLocalName(qName.localName())); + } + + targetNode.addField(fieldItem, value, targetType); + } else { + // we add an empty entry here, that makes comparison easier later on + targetNode.addField(QXmlItem(), QString(), SchemaType::Ptr()); + } + } + + targetNodeSet.insert(targetNode); + + item = resultItems.next(); + } + + // copy all items from target node set to qualified node set, that have no empty fields + QSetIterator it(targetNodeSet); + while (it.hasNext()) { + const TargetNode node = it.next(); + if (node.emptyFieldsCount() == 0) + qualifiedNodeSet.insert(node); + } + + return true; +} + +XsdElement::Ptr XsdValidatingInstanceReader::elementByName(const QXmlName &name) const +{ + return m_schema->element(name); +} + +XsdAttribute::Ptr XsdValidatingInstanceReader::attributeByName(const QXmlName &name) const +{ + return m_schema->attribute(name); +} + +SchemaType::Ptr XsdValidatingInstanceReader::typeByName(const QXmlName &name) const +{ + const SchemaType::Ptr type = m_schema->type(name); + if (type) + return type; + + return m_context->schemaTypeFactory()->createSchemaType(name); +} + +void XsdValidatingInstanceReader::addIdIdRefBinding(const QString &id, const NamedSchemaComponent::Ptr &binding) +{ + if (!m_model->idIdRefBindings(id).isEmpty()) { + error(QtXmlPatterns::tr("ID value '%1' is not unique").arg(formatKeyword(id))); + return; + } + + m_model->addIdIdRefBinding(id, binding); +} + +QString XsdValidatingInstanceReader::qNameAttribute(const QXmlName &attributeName) +{ + const QString value = attribute(attributeName).simplified(); + if (!XPathHelper::isQName(value)) { + error(QtXmlPatterns::tr("'%1' attribute contains invalid QName content: %2").arg(m_namePool->displayName(attributeName)).arg(formatData(value))); + return QString(); + } else { + return value; + } +} + +XsdComplexType::Ptr XsdValidatingInstanceReader::anyType() +{ + if (m_anyType) + return m_anyType; + + const XsdWildcard::Ptr wildcard(new XsdWildcard()); + wildcard->namespaceConstraint()->setVariety(XsdWildcard::NamespaceConstraint::Any); + wildcard->setProcessContents(XsdWildcard::Lax); + + const XsdParticle::Ptr outerParticle(new XsdParticle()); + outerParticle->setMinimumOccurs(1); + outerParticle->setMaximumOccurs(1); + + const XsdParticle::Ptr innerParticle(new XsdParticle()); + innerParticle->setMinimumOccurs(0); + innerParticle->setMaximumOccursUnbounded(true); + innerParticle->setTerm(wildcard); + + const XsdModelGroup::Ptr outerModelGroup(new XsdModelGroup()); + outerModelGroup->setCompositor(XsdModelGroup::SequenceCompositor); + outerModelGroup->setParticles(XsdParticle::List() << innerParticle); + outerParticle->setTerm(outerModelGroup); + + m_anyType = XsdComplexType::Ptr(new XsdComplexType()); + m_anyType->setName(BuiltinTypes::xsAnyType->name(m_namePool)); + m_anyType->setDerivationMethod(XsdComplexType::DerivationRestriction); + m_anyType->contentType()->setVariety(XsdComplexType::ContentType::Mixed); + m_anyType->contentType()->setParticle(outerParticle); + m_anyType->setAttributeWildcard(wildcard); + m_anyType->setIsAbstract(false); + + return m_anyType; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdvalidatinginstancereader_p.h b/src/xmlpatterns/schema/qxsdvalidatinginstancereader_p.h new file mode 100644 index 0000000..799ab44 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdvalidatinginstancereader_p.h @@ -0,0 +1,266 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdValidatingInstanceReader_H +#define Patternist_XsdValidatingInstanceReader_H + +#include "qxsdidchelper_p.h" +#include "qxsdinstancereader_p.h" +#include "qxsdstatemachine_p.h" +#include "qxsdvalidatedxmlnodemodel_p.h" + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QXmlQuery; + +namespace QPatternist +{ + /** + * @short The validating schema instance reader. + * + * This class reads in a xml instance document from a QAbstractXmlNodeModel and + * validates it against a given xml schema. + * + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdValidatingInstanceReader : public XsdInstanceReader + { + public: + typedef QExplicitlySharedDataPointer Ptr; + + /** + * Creates a new validating instance reader that reads the data from + * the given @p model. + * + * @param model The model the data shall be read from. + * @param documentUri The uri of the document the model is from. + * @param context The context that is used to report errors etc. + */ + XsdValidatingInstanceReader(const XsdValidatedXmlNodeModel *model, const QUrl &documentUri, const XsdSchemaContext::Ptr &context); + + /** + * Adds a new @p schema to the pool of schemas that shall be used + * for validation. + * The schema is located at the given @p url. + */ + void addSchema(const XsdSchema::Ptr &schema, const QUrl &url); + + /** + * Reads and validates the instance document. + */ + bool read(); + + private: + /** + * Loads a schema with the given @p targetNamespace from the given @p location + * and adds it to the pool of schemas that are used for validation. + * + * This method is used to load schemas defined in the xsi:schemaLocation or + * xsi:noNamespaceSchemaLocation attributes in the instance document. + */ + bool loadSchema(const QString &targetNamespace, const QUrl &location); + + /** + * Reports an error via the report context. + */ + void error(const QString &msg) const; + + /** + * Validates the current element tag of the instance document. + * + * @param hasStateMachine Used to remember whether this element represents the start tag + * of a complex type and therefor pushes a new state machine on the stack. + * @param element Used to remember which element has been validated in this step. + */ + bool validate(bool &hasStateMachine, XsdElement::Ptr &element); + + /** + * Validates the current tag of the instance document against the given element @p declaration. + * + * @param declaration The element declaration to validate against. + * @param hasStateMachine Used to remember whether this element represents the start tag + * of a complex type and therefor pushes a new state machine on the stack. + */ + bool validateElement(const XsdElement::Ptr &declaration, bool &hasStateMachine); + + /** + * Validates the current tag of the instance document against the given @p type of the element @p declaration. + * + * @param declaration The element declaration to validate against. + * @param type The type to validate against. + * @param isNilled Defines whether the element is nilled by the instance document. + * @param hasStateMachine Used to remember whether this element represents the start tag + * of a complex type and therefor pushes a new state machine on the stack. + * + * @note The @p type can differ from the element @p declaration type if the instance document has defined + * it via xsi:type attribute. + */ + bool validateElementType(const XsdElement::Ptr &declaration, const SchemaType::Ptr &type, bool isNilled, bool &hasStateMachine); + + /** + * Validates the current tag of the instance document against the given simple @p type of the element @p declaration. + * + * @param declaration The element declaration to validate against. + * @param type The type to validate against. + * @param isNilled Defines whether the element is nilled by the instance document. + * + * @note The @p type can differ from the element @p declaration type if the instance document has defined + * it via xsi:type attribute. + */ + bool validateElementSimpleType(const XsdElement::Ptr &declaration, const SchemaType::Ptr &type, bool isNilled); + + /** + * Validates the current tag of the instance document against the given complex @p type of the element @p declaration. + * + * @param declaration The element declaration to validate against. + * @param type The type to validate against. + * @param isNilled Defines whether the element is nilled by the instance document. + * @param hasStateMachine Used to remember whether this element represents the start tag + * of a complex type and therefor pushes a new state machine on the stack. + * + * @note The @p type can differ from the element @p declaration type if the instance document has defined + * it via xsi:type attribute. + */ + bool validateElementComplexType(const XsdElement::Ptr &declaration, const SchemaType::Ptr &type, bool isNilled, bool &hasStateMachine); + + /** + * Validates the given @p value against the attribute use @p declaration. + */ + bool validateAttribute(const XsdAttributeUse::Ptr &declaration, const QString &value); + + /** + * Validates the given @p value against the attribute @p declaration. + */ + bool validateAttribute(const XsdAttribute::Ptr &declaration, const QString &value); + + /** + * Validates the given @p attributeName against the @p wildcard. + */ + bool validateAttributeWildcard(const QXmlName &attributeName, const XsdWildcard::Ptr &wildcard); + + /** + * Validates the identity constraints of an @p element. + */ + bool validateIdentityConstraint(const XsdElement::Ptr &element, const QXmlItem ¤tItem); + + /** + * Validates the unique identity @p constraint of the @p element. + */ + bool validateUniqueIdentityConstraint(const XsdElement::Ptr &element, const XsdIdentityConstraint::Ptr &constraint, const TargetNode::Set &qualifiedNodeSet); + + /** + * Validates the key identity @p constraint of the @p element. + */ + bool validateKeyIdentityConstraint(const XsdElement::Ptr &element, const XsdIdentityConstraint::Ptr &constraint, const TargetNode::Set &targetNodeSet, const TargetNode::Set &qualifiedNodeSet); + + /** + * Validates the keyref identity @p constraint of the @p element. + */ + bool validateKeyRefIdentityConstraint(const XsdElement::Ptr &element, const XsdIdentityConstraint::Ptr &constraint, const TargetNode::Set &qualifiedNodeSet); + + /** + * Selects two sets of nodes that match the given identity @p constraint. + * + * @param element The element the identity constraint belongs to. + * @param currentItem The current element that will be used as focus for the XQuery. + * @param constraint The constraint (selector and fields) that describe the two sets. + * @param targetNodeSet The target node set as defined by the schema specification. + * @param qualifiedNodeSet The qualified node set as defined by the schema specification. + */ + bool selectNodeSets(const XsdElement::Ptr &element, const QXmlItem ¤tItem, const XsdIdentityConstraint::Ptr &constraint, TargetNode::Set &targetNodeSet, TargetNode::Set &qualifiedNodeSet); + + /** + * Creates an QXmlQuery object with the defined @p namespaceBindings that has the @p contextNode as focus + * and will execute @p query. + */ + QXmlQuery createXQuery(const QList &namespaceBindings, const QXmlItem &contextNode, const QString &query) const; + + /** + * Returns the element declaration with the given @p name from the pool of all schemas. + */ + XsdElement::Ptr elementByName(const QXmlName &name) const; + + /** + * Returns the attribute declaration with the given @p name from the pool of all schemas. + */ + XsdAttribute::Ptr attributeByName(const QXmlName &name) const; + + /** + * Returns the type declaration with the given @p name from the pool of all schemas. + */ + SchemaType::Ptr typeByName(const QXmlName &name) const; + + /** + * Adds the ID/IDREF binding to the validated model and checks for duplicates. + */ + void addIdIdRefBinding(const QString &id, const NamedSchemaComponent::Ptr &binding); + + /** + * Helper method that reads an attribute of type xs:QName and does + * syntax checking. + */ + QString qNameAttribute(const QXmlName &attributeName); + + /** + * Returns the xs:anyType that is used to build up the state machine. + * We need that as the BuiltinTypes::xsAnyType is not a XsdComplexType. + */ + XsdComplexType::Ptr anyType(); + + /** + * Helper method that creates a state machine for the given @p particle + * and pushes it on the state machine stack. + */ + void createAndPushStateMachine(const XsdParticle::Ptr &particle); + + typedef QHash MergedSchemas; + typedef QHashIterator MergedSchemasIterator; + + XsdValidatedXmlNodeModel::Ptr m_model; + MergedSchemas m_mergedSchemas; + XsdSchema::Ptr m_schema; + const NamePool::Ptr m_namePool; + const QXmlName m_xsiNilName; + const QXmlName m_xsiTypeName; + const QXmlName m_xsiSchemaLocationName; + const QXmlName m_xsiNoNamespaceSchemaLocationName; + + QStack > m_stateMachines; + QUrl m_documentUri; + XsdComplexType::Ptr m_anyType; + QSet m_processedNamespaces; + QSet m_processedSchemaLocations; + QSet m_idRefs; + QHash m_idcKeys; + SchemaType::Ptr m_idRefsType; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsdwildcard.cpp b/src/xmlpatterns/schema/qxsdwildcard.cpp new file mode 100644 index 0000000..6efb996 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdwildcard.cpp @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qxsdwildcard_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +QString XsdWildcard::absentNamespace() +{ + return QLatin1String("__ns_absent"); +} + +void XsdWildcard::NamespaceConstraint::setVariety(Variety variety) +{ + m_variety = variety; +} + +XsdWildcard::NamespaceConstraint::Variety XsdWildcard::NamespaceConstraint::variety() const +{ + return m_variety; +} + +void XsdWildcard::NamespaceConstraint::setNamespaces(const QSet &namespaces) +{ + m_namespaces = namespaces; +} + +QSet XsdWildcard::NamespaceConstraint::namespaces() const +{ + return m_namespaces; +} + +void XsdWildcard::NamespaceConstraint::setDisallowedNames(const QSet &names) +{ + m_disallowedNames = names; +} + +QSet XsdWildcard::NamespaceConstraint::disallowedNames() const +{ + return m_disallowedNames; +} + +XsdWildcard::XsdWildcard() + : m_namespaceConstraint(new NamespaceConstraint()) + , m_processContents(Strict) +{ + m_namespaceConstraint->setVariety(NamespaceConstraint::Any); +} + +bool XsdWildcard::isWildcard() const +{ + return true; +} + +void XsdWildcard::setNamespaceConstraint(const NamespaceConstraint::Ptr &namespaceConstraint) +{ + m_namespaceConstraint = namespaceConstraint; +} + +XsdWildcard::NamespaceConstraint::Ptr XsdWildcard::namespaceConstraint() const +{ + return m_namespaceConstraint; +} + +void XsdWildcard::setProcessContents(ProcessContents contents) +{ + m_processContents = contents; +} + +XsdWildcard::ProcessContents XsdWildcard::processContents() const +{ + return m_processContents; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdwildcard_p.h b/src/xmlpatterns/schema/qxsdwildcard_p.h new file mode 100644 index 0000000..8fbecb3 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdwildcard_p.h @@ -0,0 +1,169 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdWildcard_H +#define Patternist_XsdWildcard_H + +#include "qxsdterm_p.h" + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Represents a XSD wildcard object. + * + * This class represents the wildcard object of a XML schema as described + * here. + * + * It contains information from either an any object or an anyAttribute object. + * + * @see XML Schema API reference + * @ingroup Patternist_schema + * @author Tobias Koenig + */ + class XsdWildcard : public XsdTerm + { + public: + typedef QExplicitlySharedDataPointer Ptr; + + /** + * Defines the absent namespace that is used in wildcards. + */ + static QString absentNamespace(); + + /** + * Describes the namespace constraint of the wildcard. + */ + class NamespaceConstraint : public QSharedData + { + public: + typedef QExplicitlySharedDataPointer Ptr; + + /** + * Describes the variety of the namespace constraint. + * + * @see Variety Definition + */ + enum Variety + { + Any, ///< Any namespace is allowed. + Enumeration, ///< Namespaces in the namespaces set are allowed. + Not ///< Namespaces in the namespaces set are not allowed. + }; + + /** + * Sets the @p variety of the namespace constraint. + * + * @see Variety Definition + */ + void setVariety(Variety variety); + + /** + * Returns the variety of the namespace constraint. + */ + Variety variety() const; + + /** + * Sets the set of @p namespaces of the namespace constraint. + */ + void setNamespaces(const QSet &namespaces); + + /** + * Returns the set of namespaces of the namespace constraint. + */ + QSet namespaces() const; + + /** + * Sets the set of disallowed @p names of the namespace constraint. + */ + void setDisallowedNames(const QSet &names); + + /** + * Returns the set of disallowed names of the namespace constraint. + */ + QSet disallowedNames() const; + + private: + Variety m_variety; + QSet m_namespaces; + QSet m_disallowedNames; + }; + + /** + * Describes the type of content processing of the wildcard. + */ + enum ProcessContents + { + Strict, ///< There must be a top-level declaration for the item available, or the item must have an xsi:type, and the item must be valid as appropriate. + Lax, ///< If the item has a uniquely determined declaration available, it must be valid with respect to that definition. + Skip ///< No constraints at all: the item must simply be well-formed XML. + }; + + /** + * Creates a new wildcard object. + */ + XsdWildcard(); + + /** + * Returns always @c true, used to avoid dynamic casts. + */ + virtual bool isWildcard() const; + + /** + * Sets the namespace @p constraint of the wildcard. + * + * @see Namespace Constraint Definition + */ + void setNamespaceConstraint(const NamespaceConstraint::Ptr &constraint); + + /** + * Returns the namespace constraint of the wildcard. + */ + NamespaceConstraint::Ptr namespaceConstraint() const; + + /** + * Sets the process @p contents of the wildcard. + * + * @see Process Contents Definition + */ + void setProcessContents(ProcessContents contents); + + /** + * Returns the process contents of the wildcard. + */ + ProcessContents processContents() const; + + private: + NamespaceConstraint::Ptr m_namespaceConstraint; + ProcessContents m_processContents; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/qxsdxpathexpression.cpp b/src/xmlpatterns/schema/qxsdxpathexpression.cpp new file mode 100644 index 0000000..ba9d0a4 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdxpathexpression.cpp @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qxsdxpathexpression_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +void XsdXPathExpression::setNamespaceBindings(const QList &set) +{ + m_namespaceBindings = set; +} + +QList XsdXPathExpression::namespaceBindings() const +{ + return m_namespaceBindings; +} + +void XsdXPathExpression::setDefaultNamespace(const AnyURI::Ptr &defaultNs) +{ + m_defaultNamespace = defaultNs; +} + +AnyURI::Ptr XsdXPathExpression::defaultNamespace() const +{ + return m_defaultNamespace; +} + +void XsdXPathExpression::setBaseURI(const AnyURI::Ptr &uri) +{ + m_baseURI = uri; +} + +AnyURI::Ptr XsdXPathExpression::baseURI() const +{ + return m_baseURI; +} + +void XsdXPathExpression::setExpression(const QString &expression) +{ + m_expression = expression; +} + +QString XsdXPathExpression::expression() const +{ + return m_expression; +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/schema/qxsdxpathexpression_p.h b/src/xmlpatterns/schema/qxsdxpathexpression_p.h new file mode 100644 index 0000000..e57f7b7 --- /dev/null +++ b/src/xmlpatterns/schema/qxsdxpathexpression_p.h @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_XsdXPathExpression_H +#define Patternist_XsdXPathExpression_H + +#include "qanyuri_p.h" +#include "qnamedschemacomponent_p.h" +#include "qxsdannotated_p.h" + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Represents a XSD assertion object. + * + * @ingroup Patternist_schema + * @author Tobias Koenig + * @see XPathExpression Definition + */ + class XsdXPathExpression : public NamedSchemaComponent, public XsdAnnotated + { + public: + typedef QExplicitlySharedDataPointer Ptr; + typedef QList List; + + /** + * Sets the list of namespace @p bindings of the XPath expression. + * + * @see Namespace Bindings Definition + * + * @note We can't use a QSet here, as the hash method does not take the prefix + * in account, so we loose entries. + */ + void setNamespaceBindings(const QList &bindings); + + /** + * Returns the list of namespace bindings of the XPath expression. + */ + QList namespaceBindings() const; + + /** + * Sets the default namespace of the XPath expression. + * + * @see Default Namespace Definition + */ + void setDefaultNamespace(const AnyURI::Ptr &defaultNamespace); + + /** + * Returns the default namespace of the XPath expression. + */ + AnyURI::Ptr defaultNamespace() const; + + /** + * Sets the base @p uri of the XPath expression. + * + * @see Base URI Definition + */ + void setBaseURI(const AnyURI::Ptr &uri); + + /** + * Returns the base uri of the XPath expression. + */ + AnyURI::Ptr baseURI() const; + + /** + * Sets the @p expression string of the XPath expression. + * + * @see Expression Definition + */ + void setExpression(const QString &expression); + + /** + * Returns the expression string of the XPath expression. + */ + QString expression() const; + + private: + QList m_namespaceBindings; + AnyURI::Ptr m_defaultNamespace; + AnyURI::Ptr m_baseURI; + QString m_expression; + }; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/schema/schema.pri b/src/xmlpatterns/schema/schema.pri new file mode 100644 index 0000000..b00d64b --- /dev/null +++ b/src/xmlpatterns/schema/schema.pri @@ -0,0 +1,93 @@ +HEADERS += $$PWD/qnamespacesupport_p.h \ + $$PWD/qxsdalternative_p.h \ + $$PWD/qxsdannotated_p.h \ + $$PWD/qxsdannotation_p.h \ + $$PWD/qxsdapplicationinformation_p.h \ + $$PWD/qxsdassertion_p.h \ + $$PWD/qxsdattribute_p.h \ + $$PWD/qxsdattributereference_p.h \ + $$PWD/qxsdattributeterm_p.h \ + $$PWD/qxsdattributeuse_p.h \ + $$PWD/qxsdattributegroup_p.h \ + $$PWD/qxsdcomplextype_p.h \ + $$PWD/qxsddocumentation_p.h \ + $$PWD/qxsdelement_p.h \ + $$PWD/qxsdfacet_p.h \ + $$PWD/qxsdidcache_p.h \ + $$PWD/qxsdidchelper_p.h \ + $$PWD/qxsdidentityconstraint_p.h \ + $$PWD/qxsdinstancereader_p.h \ + $$PWD/qxsdmodelgroup_p.h \ + $$PWD/qxsdnotation_p.h \ + $$PWD/qxsdparticle_p.h \ + $$PWD/qxsdparticlechecker_p.h \ + $$PWD/qxsdreference_p.h \ + $$PWD/qxsdsimpletype_p.h \ + $$PWD/qxsdschema_p.h \ + $$PWD/qxsdschemachecker_p.h \ + $$PWD/qxsdschemacontext_p.h \ + $$PWD/qxsdschemadebugger_p.h \ + $$PWD/qxsdschemahelper_p.h \ + $$PWD/qxsdschemamerger_p.h \ + $$PWD/qxsdschemaparser_p.h \ + $$PWD/qxsdschemaparsercontext_p.h \ + $$PWD/qxsdschemaresolver_p.h \ + $$PWD/qxsdschematoken_p.h \ + $$PWD/qxsdschematypesfactory_p.h \ + $$PWD/qxsdstatemachine_p.h \ + $$PWD/qxsdstatemachinebuilder_p.h \ + $$PWD/qxsdterm_p.h \ + $$PWD/qxsdtypechecker_p.h \ + $$PWD/qxsduserschematype_p.h \ + $$PWD/qxsdvalidatedxmlnodemodel_p.h \ + $$PWD/qxsdvalidatinginstancereader_p.h \ + $$PWD/qxsdwildcard_p.h \ + $$PWD/qxsdxpathexpression_p.h + +SOURCES += $$PWD/qnamespacesupport.cpp \ + $$PWD/qxsdalternative.cpp \ + $$PWD/qxsdannotated.cpp \ + $$PWD/qxsdannotation.cpp \ + $$PWD/qxsdapplicationinformation.cpp \ + $$PWD/qxsdassertion.cpp \ + $$PWD/qxsdattribute.cpp \ + $$PWD/qxsdattributereference.cpp \ + $$PWD/qxsdattributeterm.cpp \ + $$PWD/qxsdattributeuse.cpp \ + $$PWD/qxsdattributegroup.cpp \ + $$PWD/qxsdcomplextype.cpp \ + $$PWD/qxsddocumentation.cpp \ + $$PWD/qxsdelement.cpp \ + $$PWD/qxsdfacet.cpp \ + $$PWD/qxsdidcache.cpp \ + $$PWD/qxsdidchelper.cpp \ + $$PWD/qxsdidentityconstraint.cpp \ + $$PWD/qxsdinstancereader.cpp \ + $$PWD/qxsdmodelgroup.cpp \ + $$PWD/qxsdnotation.cpp \ + $$PWD/qxsdparticle.cpp \ + $$PWD/qxsdparticlechecker.cpp \ + $$PWD/qxsdreference.cpp \ + $$PWD/qxsdsimpletype.cpp \ + $$PWD/qxsdschema.cpp \ + $$PWD/qxsdschemachecker.cpp \ + $$PWD/qxsdschemachecker_setup.cpp \ + $$PWD/qxsdschemacontext.cpp \ + $$PWD/qxsdschemadebugger.cpp \ + $$PWD/qxsdschemahelper.cpp \ + $$PWD/qxsdschemamerger.cpp \ + $$PWD/qxsdschemaparser.cpp \ + $$PWD/qxsdschemaparser_setup.cpp \ + $$PWD/qxsdschemaparsercontext.cpp \ + $$PWD/qxsdschemaresolver.cpp \ + $$PWD/qxsdschematoken.cpp \ + $$PWD/qxsdschematypesfactory.cpp \ + $$PWD/qxsdstatemachinebuilder.cpp \ + $$PWD/qxsdterm.cpp \ + $$PWD/qxsdtypechecker.cpp \ + $$PWD/qxsdwildcard.cpp \ + $$PWD/qxsdvalidatedxmlnodemodel.cpp \ + $$PWD/qxsdvalidatinginstancereader.cpp \ + $$PWD/qxsdxpathexpression.cpp + +RESOURCES += $$PWD/builtinschemas.qrc diff --git a/src/xmlpatterns/schema/schemas/xml.xsd b/src/xmlpatterns/schema/schemas/xml.xsd new file mode 100644 index 0000000..eeb9db5 --- /dev/null +++ b/src/xmlpatterns/schema/schemas/xml.xsd @@ -0,0 +1,145 @@ + + + + + + See http://www.w3.org/XML/1998/namespace.html and + http://www.w3.org/TR/REC-xml for information about this namespace. + + This schema document describes the XML namespace, in a form + suitable for import by other schema documents. + + Note that local names in this namespace are intended to be defined + only by the World Wide Web Consortium or its subgroups. The + following names are currently defined in this namespace and should + not be used with conflicting semantics by any Working Group, + specification, or document instance: + + base (as an attribute name): denotes an attribute whose value + provides a URI to be used as the base for interpreting any + relative URIs in the scope of the element on which it + appears; its value is inherited. This name is reserved + by virtue of its definition in the XML Base specification. + + id (as an attribute name): denotes an attribute whose value + should be interpreted as if declared to be of type ID. + This name is reserved by virtue of its definition in the + xml:id specification. + + lang (as an attribute name): denotes an attribute whose value + is a language code for the natural language of the content of + any element; its value is inherited. This name is reserved + by virtue of its definition in the XML specification. + + space (as an attribute name): denotes an attribute whose + value is a keyword indicating what whitespace processing + discipline is intended for the content of the element; its + value is inherited. This name is reserved by virtue of its + definition in the XML specification. + + Father (in any context at all): denotes Jon Bosak, the chair of + the original XML Working Group. This name is reserved by + the following decision of the W3C XML Plenary and + XML Coordination groups: + + In appreciation for his vision, leadership and dedication + the W3C XML Plenary on this 10th day of February, 2000 + reserves for Jon Bosak in perpetuity the XML name + xml:Father + + + + + This schema defines attributes and an attribute group + suitable for use by + schemas wishing to allow xml:base, xml:lang, xml:space or xml:id + attributes on elements they define. + + To enable this, such a schema must import this schema + for the XML namespace, e.g. as follows: + <schema . . .> + . . . + <import namespace="http://www.w3.org/XML/1998/namespace" + schemaLocation="http://www.w3.org/2001/xml.xsd"/> + + Subsequently, qualified reference to any of the attributes + or the group defined below will have the desired effect, e.g. + + <type . . .> + . . . + <attributeGroup ref="xml:specialAttrs"/> + + will define a type which will schema-validate an instance + element with any of those attributes + + + + In keeping with the XML Schema WG's standard versioning + policy, this schema document will persist at + http://www.w3.org/2007/08/xml.xsd. + At the date of issue it can also be found at + http://www.w3.org/2001/xml.xsd. + The schema document at that URI may however change in the future, + in order to remain compatible with the latest version of XML Schema + itself, or with the XML namespace itself. In other words, if the XML + Schema or XML namespaces change, the version of this document at + http://www.w3.org/2001/xml.xsd will change + accordingly; the version at + http://www.w3.org/2007/08/xml.xsd will not change. + + + + + + Attempting to install the relevant ISO 2- and 3-letter + codes as the enumerated possible values is probably never + going to be a realistic possibility. See + RFC 3066 at http://www.ietf.org/rfc/rfc3066.txt and the IANA registry + at http://www.iana.org/assignments/lang-tag-apps.htm for + further information. + + The union allows for the 'un-declaration' of xml:lang with + the empty string. + + + + + + + + + + + + + + + + + + + + + + + + See http://www.w3.org/TR/xmlbase/ for + information about this attribute. + + + + + + See http://www.w3.org/TR/xml-id/ for + information about this attribute. + + + + + + + + + + + diff --git a/src/xmlpatterns/schema/tokens.xml b/src/xmlpatterns/schema/tokens.xml new file mode 100644 index 0000000..7ec9752 --- /dev/null +++ b/src/xmlpatterns/schema/tokens.xml @@ -0,0 +1,125 @@ + + + + abstract + all + alternative + annotation + any + anyAttribute + appinfo + appliesToEmpty + assert + assertion + attribute + attributeFormDefault + attributeGroup + base + block + blockDefault + choice + collapse + complexContent + complexType + default + defaultAttributes + defaultAttributesApply + defaultOpenContent + documentation + element + elementFormDefault + enumeration + extension + field + final + finalDefault + fixed + form + fractionDigits + group + id + import + include + itemType + key + keyref + length + list + maxExclusive + maxInclusive + maxLength + maxOccurs + memberTypes + minExclusive + minInclusive + minLength + minOccurs + mixed + mode + name + namespace + nillable + notation + notNamespace + notQName + openContent + override + preserve + pattern + processContents + public + redefine + ref + refer + replace + restriction + schema + schemaLocation + selector + sequence + simpleContent + simpleType + source + substitutionGroup + system + targetNamespace + test + totalDigits + type + union + unique + use + value + version + whiteSpace + xpath + xpathDefaultNamespace + xml:lang + http://www.w3.org/2001/XMLSchema + + + + + /**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + + + + + + diff --git a/src/xmlpatterns/type/qanysimpletype.cpp b/src/xmlpatterns/type/qanysimpletype.cpp index c685d54..81120a7 100644 --- a/src/xmlpatterns/type/qanysimpletype.cpp +++ b/src/xmlpatterns/type/qanysimpletype.cpp @@ -80,4 +80,14 @@ SchemaType::DerivationMethod AnySimpleType::derivationMethod() const return DerivationRestriction; } +bool AnySimpleType::isSimpleType() const +{ + return true; +} + +bool AnySimpleType::isComplexType() const +{ + return false; +} + QT_END_NAMESPACE diff --git a/src/xmlpatterns/type/qanysimpletype_p.h b/src/xmlpatterns/type/qanysimpletype_p.h index b91c7d0..ebd4b5f 100644 --- a/src/xmlpatterns/type/qanysimpletype_p.h +++ b/src/xmlpatterns/type/qanysimpletype_p.h @@ -73,6 +73,8 @@ namespace QPatternist class AnySimpleType : public AnyType { public: + typedef QExplicitlySharedDataPointer Ptr; + typedef QList List; friend class BuiltinTypes; virtual ~AnySimpleType(); @@ -105,6 +107,16 @@ namespace QPatternist */ virtual SchemaType::DerivationMethod derivationMethod() const; + /** + * Always returns @c true. + */ + virtual bool isSimpleType() const; + + /** + * Always returns @c false. + */ + virtual bool isComplexType() const; + protected: AnySimpleType(); diff --git a/src/xmlpatterns/type/qanytype.cpp b/src/xmlpatterns/type/qanytype.cpp index 95ad2b3..19f029f 100644 --- a/src/xmlpatterns/type/qanytype.cpp +++ b/src/xmlpatterns/type/qanytype.cpp @@ -69,7 +69,7 @@ QXmlName AnyType::name(const NamePool::Ptr &np) const return np->allocateQName(StandardNamespaces::xs, QLatin1String("anyType")); } -QString AnyType::displayName(const NamePool::Ptr &) const +QString AnyType::displayName(const NamePool::Ptr &np) const { /* A bit faster than calling name()->displayName() */ return QLatin1String("xs:anyType"); @@ -85,9 +85,19 @@ SchemaType::TypeCategory AnyType::category() const return None; } +bool AnyType::isComplexType() const +{ + return true; +} + SchemaType::DerivationMethod AnyType::derivationMethod() const { return NoDerivation; } +SchemaType::DerivationConstraints AnyType::derivationConstraints() const +{ + return SchemaType::DerivationConstraints(); +} + QT_END_NAMESPACE diff --git a/src/xmlpatterns/type/qanytype_p.h b/src/xmlpatterns/type/qanytype_p.h index 70477af..8f2505e 100644 --- a/src/xmlpatterns/type/qanytype_p.h +++ b/src/xmlpatterns/type/qanytype_p.h @@ -114,6 +114,16 @@ namespace QPatternist */ virtual DerivationMethod derivationMethod() const; + /** + * @returns an empty set of derivation constraint flags. + */ + virtual DerivationConstraints derivationConstraints() const; + + /** + * Always returns @c true. + */ + virtual bool isComplexType() const; + protected: /** * @short This constructor is protected, because this diff --git a/src/xmlpatterns/type/qnamedschemacomponent.cpp b/src/xmlpatterns/type/qnamedschemacomponent.cpp new file mode 100644 index 0000000..e45b9b6 --- /dev/null +++ b/src/xmlpatterns/type/qnamedschemacomponent.cpp @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qnamedschemacomponent_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QPatternist; + +NamedSchemaComponent::NamedSchemaComponent() +{ +} + +NamedSchemaComponent::~NamedSchemaComponent() +{ +} + +void NamedSchemaComponent::setName(const QXmlName &name) +{ + m_name = name; +} + +QXmlName NamedSchemaComponent::name(const NamePool::Ptr&) const +{ + return m_name; +} + +QString NamedSchemaComponent::displayName(const NamePool::Ptr &np) const +{ + return np->displayName(m_name); +} + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/type/qnamedschemacomponent_p.h b/src/xmlpatterns/type/qnamedschemacomponent_p.h new file mode 100644 index 0000000..bc3121b --- /dev/null +++ b/src/xmlpatterns/type/qnamedschemacomponent_p.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +// +// 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. + +#ifndef Patternist_NamedSchemaComponent_H +#define Patternist_NamedSchemaComponent_H + +#include "qnamepool_p.h" +#include "qschemacomponent_p.h" +#include "qxmlname.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +namespace QPatternist +{ + /** + * @short Base class for all named components that can appear in a W3C XML Schema. + * + * @ingroup Patternist_types + * @author Tobias Koenig + */ + class NamedSchemaComponent : public SchemaComponent + { + public: + typedef QExplicitlySharedDataPointer Ptr; + + /** + * Describes the blocking constraints that are given by the 'block' attributes. + */ + enum BlockingConstraint + { + RestrictionConstraint = 1, + ExtensionConstraint = 2, + SubstitutionConstraint = 4 + }; + Q_DECLARE_FLAGS(BlockingConstraints, BlockingConstraint) + + /** + * Creates a new named schema component. + */ + NamedSchemaComponent(); + + /** + * Destroys the named schema component. + */ + virtual ~NamedSchemaComponent(); + + /** + * Sets the @p name of the schema component. + */ + void setName(const QXmlName &name); + + /** + * Returns the name of the schema component. + * + * @param namePool The name pool the name belongs to. + */ + virtual QXmlName name(const NamePool::Ptr &namePool) const; + + /** + * Returns the display name of the schema component. + * + * @param namePool The name pool the name belongs to. + */ + virtual QString displayName(const NamePool::Ptr &namePool) const; + + private: + QXmlName m_name; + }; + + Q_DECLARE_OPERATORS_FOR_FLAGS(NamedSchemaComponent::BlockingConstraints) +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/src/xmlpatterns/type/qprimitives_p.h b/src/xmlpatterns/type/qprimitives_p.h index 354b690..a1a41ae 100644 --- a/src/xmlpatterns/type/qprimitives_p.h +++ b/src/xmlpatterns/type/qprimitives_p.h @@ -53,6 +53,8 @@ #define Patternist_Primitives_H #include +#include +#include /** * @file @@ -72,6 +74,17 @@ QT_BEGIN_NAMESPACE class QString; /** + * @internal + * + * A method to allow a QHash or QSet with QUrl + * as key type. + */ +inline uint qHash(const QUrl &uri) +{ + return qHash(uri.toString()); +} + +/** * @short The namespace for the internal API of QtXmlPatterns * @internal */ diff --git a/src/xmlpatterns/type/qschematype.cpp b/src/xmlpatterns/type/qschematype.cpp index b4d6bc0..1ffd151 100644 --- a/src/xmlpatterns/type/qschematype.cpp +++ b/src/xmlpatterns/type/qschematype.cpp @@ -72,4 +72,9 @@ bool SchemaType::isComplexType() const return category() == ComplexType; } +bool SchemaType::isDefinedBySchema() const +{ + return false; +} + QT_END_NAMESPACE diff --git a/src/xmlpatterns/type/qschematype_p.h b/src/xmlpatterns/type/qschematype_p.h index 30f63c8..ca59bdc 100644 --- a/src/xmlpatterns/type/qschematype_p.h +++ b/src/xmlpatterns/type/qschematype_p.h @@ -57,6 +57,7 @@ #include "qxmlname.h" template class QHash; +template class QList; QT_BEGIN_HEADER @@ -80,6 +81,7 @@ namespace QPatternist typedef QExplicitlySharedDataPointer Ptr; typedef QHash Hash; + typedef QList List; /** * Schema types are divided into different categories such as @@ -117,6 +119,18 @@ namespace QPatternist NoDerivation = 16 }; + /** + * Describes the derivation constraints that are given by the 'final' or 'block' attributes. + */ + enum DerivationConstraint + { + RestrictionConstraint = 1, + ExtensionConstraint = 2, + ListConstraint = 4, + UnionConstraint = 8 + }; + Q_DECLARE_FLAGS(DerivationConstraints, DerivationConstraint) + SchemaType(); virtual ~SchemaType(); @@ -137,6 +151,11 @@ namespace QPatternist virtual DerivationMethod derivationMethod() const = 0; /** + * Determines what derivation constraints exists for the type. + */ + virtual DerivationConstraints derivationConstraints() const = 0; + + /** * Determines whether the type is an abstract type. * * @note It is important a correct value is returned, since @@ -202,7 +221,7 @@ namespace QPatternist * @note Do not re-implement this function, but instead override category() * and let it return an appropriate value. */ - bool isSimpleType() const; + virtual bool isSimpleType() const; /** * Determines whether the type is a complex type, by introspecting @@ -211,8 +230,15 @@ namespace QPatternist * @note Do not re-implement this function, but instead override category() * and let it return an appropriate value. */ - bool isComplexType() const; + virtual bool isComplexType() const; + + /** + * Returns whether the value has been defined by a schema (is not a built in type). + */ + virtual bool isDefinedBySchema() const; }; + + Q_DECLARE_OPERATORS_FOR_FLAGS(SchemaType::DerivationConstraints) } QT_END_NAMESPACE diff --git a/src/xmlpatterns/type/type.pri b/src/xmlpatterns/type/type.pri index ef5976a..5425298 100644 --- a/src/xmlpatterns/type/type.pri +++ b/src/xmlpatterns/type/type.pri @@ -24,6 +24,7 @@ HEADERS += $$PWD/qabstractnodetest_p.h \ $$PWD/qitemtype_p.h \ $$PWD/qlocalnametest_p.h \ $$PWD/qmultiitemtype_p.h \ + $$PWD/qnamedschemacomponent_p.h \ $$PWD/qnamespacenametest_p.h \ $$PWD/qnonetype_p.h \ $$PWD/qnumerictype_p.h \ @@ -57,6 +58,7 @@ SOURCES += $$PWD/qabstractnodetest.cpp \ $$PWD/qitemtype.cpp \ $$PWD/qlocalnametest.cpp \ $$PWD/qmultiitemtype.cpp \ + $$PWD/qnamedschemacomponent.cpp \ $$PWD/qnamespacenametest.cpp \ $$PWD/qnonetype.cpp \ $$PWD/qnumerictype.cpp \ diff --git a/src/xmlpatterns/utils/qpatternistlocale_p.h b/src/xmlpatterns/utils/qpatternistlocale_p.h index e3f645f..c340d95 100644 --- a/src/xmlpatterns/utils/qpatternistlocale_p.h +++ b/src/xmlpatterns/utils/qpatternistlocale_p.h @@ -168,6 +168,16 @@ namespace QPatternist } /** + * @short Formats name of any type. + */ + static inline QString formatType(const NamePool::Ptr &np, const QXmlName &name) + { + return QLatin1String("") + + escape(np->displayName(name)) + + QLatin1String(""); + } + + /** * @short Formats Cardinality. */ static inline QString formatType(const Cardinality &type) diff --git a/src/xmlpatterns/xmlpatterns.pro b/src/xmlpatterns/xmlpatterns.pro index e9d8af9..fb6aa1a 100644 --- a/src/xmlpatterns/xmlpatterns.pro +++ b/src/xmlpatterns/xmlpatterns.pro @@ -21,6 +21,8 @@ include($$PWD/iterators/iterators.pri) include($$PWD/janitors/janitors.pri) include($$PWD/parser/parser.pri) include($$PWD/projection/projection.pri) +include($$PWD/schema/schema.pri) +include($$PWD/schematron/schematron.pri) include($$PWD/type/type.pri) include($$PWD/utils/utils.pri) include($$PWD/qobjectmodel/qobjectmodel.pri) diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index 443ee7e..e8eea71 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -402,9 +402,14 @@ SUBDIRS += checkxmlfiles \ qxmlnodemodelindex \ qxmlquery \ qxmlresultitems \ + qxmlschema \ + qxmlschemavalidator \ qxmlserializer \ xmlpatterns \ xmlpatternsdiagnosticsts \ + xmlpatternsschema \ + xmlpatternsschemats \ + xmlpatternsvalidator \ xmlpatternsview \ xmlpatternsxqts \ xmlpatternsxslts diff --git a/tests/auto/qabstractxmlnodemodel/tst_qabstractxmlnodemodel.cpp b/tests/auto/qabstractxmlnodemodel/tst_qabstractxmlnodemodel.cpp index 72b43ee..9eacd90 100644 --- a/tests/auto/qabstractxmlnodemodel/tst_qabstractxmlnodemodel.cpp +++ b/tests/auto/qabstractxmlnodemodel/tst_qabstractxmlnodemodel.cpp @@ -45,6 +45,7 @@ #ifdef QTEST_XMLPATTERNS +#include #include #include #include @@ -80,6 +81,7 @@ private Q_SLOTS: void id() const; void idref() const; void typedValue() const; + void sourceLocation() const; private: QAbstractXmlNodeModel::Ptr m_nodeModel; @@ -389,6 +391,12 @@ void tst_QAbstractXmlNodeModel::typedValue() const QVERIFY(output.isEmpty()); } +void tst_QAbstractXmlNodeModel::sourceLocation() const +{ + const QAbstractXmlNodeModel* const constModel = m_nodeModel.data(); + const QSourceLocation location = constModel->sourceLocation(m_rootNode); +} + QTEST_MAIN(tst_QAbstractXmlNodeModel) #include "tst_qabstractxmlnodemodel.moc" diff --git a/tests/auto/qxmlquery/tst_qxmlquery.cpp b/tests/auto/qxmlquery/tst_qxmlquery.cpp index d457581..6d8a803 100644 --- a/tests/auto/qxmlquery/tst_qxmlquery.cpp +++ b/tests/auto/qxmlquery/tst_qxmlquery.cpp @@ -220,6 +220,10 @@ private Q_SLOTS: void bindVariableQXmlNameQXmlQuery() const; void bindVariableQXmlQueryInvalidate() const; + void identityConstraintSuccess() const; + void identityConstraintFailure() const; + void identityConstraintFailure_data() const; + // TODO call all URI resolving functions where 1) the URI resolver return a null QUrl(); 2) resolves into valid, existing URI, 3) invalid, non-existing URI. // TODO bind stringlists, variant lists, both ways. // TODO trigger serialization error, or any error in evaluateToushCallback(). @@ -2920,6 +2924,9 @@ void tst_QXmlQuery::enumQueryLanguage() const /* These enum values should be possible to OR for future plans. */ QCOMPARE(int(QXmlQuery::XQuery10), 1); QCOMPARE(int(QXmlQuery::XSLT20), 2); + QCOMPARE(int(QXmlQuery::XmlSchema11IdentityConstraintSelector), 1024); + QCOMPARE(int(QXmlQuery::XmlSchema11IdentityConstraintField), 2048); + QCOMPARE(int(QXmlQuery::XPath20), 4096); } void tst_QXmlQuery::setInitialTemplateNameQXmlName() const @@ -3222,6 +3229,157 @@ void tst_QXmlQuery::bindVariableQXmlQueryInvalidate() const QVERIFY(!query.isValid()); } +void tst_QXmlQuery::identityConstraintSuccess() const +{ + QXmlQuery::QueryLanguage queryLanguage = QXmlQuery::XmlSchema11IdentityConstraintSelector; + + /* We run this code for Selector and Field. */ + for(int i = 0; i < 3; ++i) + { + QXmlNamePool namePool; + QXmlResultItems result; + QXmlItem node; + + { + QXmlQuery nodeSource(namePool); + nodeSource.setQuery(QLatin1String("")); + + nodeSource.evaluateTo(&result); + node = result.next(); + } + + /* Basic use: + * 1. The focus is undefined, but it's still valid. + * 2. We never evaluate. */ + { + QXmlQuery query(queryLanguage); + query.setQuery(QLatin1String("a")); + QVERIFY(query.isValid()); + } + + /* Basic use: + * 1. The focus is undefined, but it's still valid. + * 2. We afterwards set the focus. */ + { + QXmlQuery query(queryLanguage, namePool); + query.setQuery(QLatin1String("a")); + query.setFocus(node); + QVERIFY(query.isValid()); + } + + /* Basic use: + * 1. The focus is undefined, but it's still valid. + * 2. We afterwards set the focus. + * 3. We evaluate. */ + { + QXmlQuery query(queryLanguage, namePool); + query.setQuery(QString(QLatin1Char('.'))); + query.setFocus(node); + QVERIFY(query.isValid()); + + QString result; + QVERIFY(query.evaluateTo(&result)); + QCOMPARE(result, QString::fromLatin1("\n")); + } + + /* A slightly more complex Field. */ + { + QXmlQuery query(queryLanguage); + query.setQuery(QLatin1String("* | .//xml:*/.")); + QVERIFY(query.isValid()); + } + + /* @ is only allowed in Field. */ + if(queryLanguage == QXmlQuery::XmlSchema11IdentityConstraintField) + { + QXmlQuery query(QXmlQuery::XmlSchema11IdentityConstraintField); + query.setQuery(QLatin1String("@abc")); + QVERIFY(query.isValid()); + } + + /* Field allows attribute:: and child:: .*/ + if(queryLanguage == QXmlQuery::XmlSchema11IdentityConstraintField) + { + QXmlQuery query(QXmlQuery::XmlSchema11IdentityConstraintField); + query.setQuery(QLatin1String("attribute::name | child::name")); + QVERIFY(query.isValid()); + } + + /* Selector allows only child:: .*/ + { + QXmlQuery query(QXmlQuery::XmlSchema11IdentityConstraintSelector); + query.setQuery(QLatin1String("child::name")); + QVERIFY(query.isValid()); + } + + if(i == 0) + queryLanguage = QXmlQuery::XmlSchema11IdentityConstraintField; + else if(i == 1) + queryLanguage = QXmlQuery::XPath20; + } +} + +Q_DECLARE_METATYPE(QXmlQuery::QueryLanguage); + +/*! + We just do some basic tests for boot strapping and sanity checking. The actual regression + testing is in the Schema suite. + */ +void tst_QXmlQuery::identityConstraintFailure() const +{ + QFETCH(QXmlQuery::QueryLanguage, queryLanguage); + QFETCH(QString, inputQuery); + + QXmlQuery query(queryLanguage); + MessageSilencer silencer; + query.setMessageHandler(&silencer); + + query.setQuery(inputQuery); + QVERIFY(!query.isValid()); +} + +void tst_QXmlQuery::identityConstraintFailure_data() const +{ + QTest::addColumn("queryLanguage"); + QTest::addColumn("inputQuery"); + + QTest::newRow("We don't have element constructors in identity constraint pattern, " + "it's an XQuery feature(Selector).") + << QXmlQuery::XmlSchema11IdentityConstraintSelector + << QString::fromLatin1(""); + + QTest::newRow("We don't have functions in identity constraint pattern, " + "it's an XPath feature(Selector).") + << QXmlQuery::XmlSchema11IdentityConstraintSelector + << QString::fromLatin1("current-time()"); + + QTest::newRow("We don't have element constructors in identity constraint pattern, " + "it's an XQuery feature(Field).") + << QXmlQuery::XmlSchema11IdentityConstraintSelector + << QString::fromLatin1(""); + + QTest::newRow("We don't have functions in identity constraint pattern, " + "it's an XPath feature(Field).") + << QXmlQuery::XmlSchema11IdentityConstraintSelector + << QString::fromLatin1("current-time()"); + + QTest::newRow("@attributeName is disallowed for the selector.") + << QXmlQuery::XmlSchema11IdentityConstraintSelector + << QString::fromLatin1("@abc"); + + QTest::newRow("attribute:: is disallowed for the selector.") + << QXmlQuery::XmlSchema11IdentityConstraintSelector + << QString::fromLatin1("attribute::name"); + + QTest::newRow("ancestor::name is disallowed for the selector.") + << QXmlQuery::XmlSchema11IdentityConstraintSelector + << QString::fromLatin1("ancestor::name"); + + QTest::newRow("ancestor::name is disallowed for the field.") + << QXmlQuery::XmlSchema11IdentityConstraintField + << QString::fromLatin1("ancestor::name"); +} + QTEST_MAIN(tst_QXmlQuery) #include "tst_qxmlquery.moc" diff --git a/tests/auto/qxmlschema/.gitignore b/tests/auto/qxmlschema/.gitignore new file mode 100644 index 0000000..5cf52a0 --- /dev/null +++ b/tests/auto/qxmlschema/.gitignore @@ -0,0 +1 @@ +tst_qxmlschema diff --git a/tests/auto/qxmlschema/qxmlschema.pro b/tests/auto/qxmlschema/qxmlschema.pro new file mode 100644 index 0000000..9dd7469 --- /dev/null +++ b/tests/auto/qxmlschema/qxmlschema.pro @@ -0,0 +1,4 @@ +load(qttest_p4) +SOURCES += tst_qxmlschema.cpp + +include (../xmlpatterns.pri) diff --git a/tests/auto/qxmlschema/tst_qxmlschema.cpp b/tests/auto/qxmlschema/tst_qxmlschema.cpp new file mode 100644 index 0000000..64012c1 --- /dev/null +++ b/tests/auto/qxmlschema/tst_qxmlschema.cpp @@ -0,0 +1,231 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +****************************************************************************/ + +#include + +#ifdef QTEST_XMLPATTERNS + +#include +#include +#include +#include +#include + +class DummyMessageHandler : public QAbstractMessageHandler +{ + public: + DummyMessageHandler(QObject *parent = 0) + : QAbstractMessageHandler(parent) + { + } + + protected: + virtual void handleMessage(QtMsgType, const QString&, const QUrl&, const QSourceLocation&) + { + } +}; + +class DummyUriResolver : public QAbstractUriResolver +{ + public: + DummyUriResolver(QObject *parent = 0) + : QAbstractUriResolver(parent) + { + } + + virtual QUrl resolve(const QUrl&, const QUrl&) const + { + return QUrl(); + } +}; + +/*! + \class tst_QXmlSchema + \internal + \brief Tests class QXmlSchema. + + This test is not intended for testing the engine, but the functionality specific + to the QXmlSchema class. + */ +class tst_QXmlSchema : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void defaultConstructor() const; + void copyConstructor() const; + void constructorQXmlNamePool() const; + + void networkAccessManagerSignature() const; + void networkAccessManagerDefaultValue() const; + void networkAccessManager() const; + + void messageHandlerSignature() const; + void messageHandlerDefaultValue() const; + void messageHandler() const; + + void uriResolverSignature() const; + void uriResolverDefaultValue() const; + void uriResolver() const; +}; + +void tst_QXmlSchema::defaultConstructor() const +{ + /* Allocate instance in different orders. */ + { + QXmlSchema schema; + } + + { + QXmlSchema schema1; + QXmlSchema schema2; + } + + { + QXmlSchema schema1; + QXmlSchema schema2; + QXmlSchema schema3; + } +} + +void tst_QXmlSchema::copyConstructor() const +{ + /* Verify that we can take a const reference, and simply do a copy of a default constructed object. */ + { + const QXmlSchema schema1; + QXmlSchema schema2(schema1); + } + + /* Copy twice. */ + { + const QXmlSchema schema1; + QXmlSchema schema2(schema1); + QXmlSchema schema3(schema2); + } + + /* Verify that copying default values works. */ + { + const QXmlSchema schema1; + const QXmlSchema schema2(schema1); + QCOMPARE(schema2.messageHandler(), schema1.messageHandler()); + QCOMPARE(schema2.uriResolver(), schema1.uriResolver()); + QCOMPARE(schema2.networkAccessManager(), schema1.networkAccessManager()); + QCOMPARE(schema2.isValid(), schema1.isValid()); + } +} + +void tst_QXmlSchema::constructorQXmlNamePool() const +{ + QXmlSchema schema; + + QXmlNamePool np = schema.namePool(); + + const QXmlName name(np, QLatin1String("localName"), + QLatin1String("http://example.com/"), + QLatin1String("prefix")); + + QXmlNamePool np2(schema.namePool()); + QCOMPARE(name.namespaceUri(np2), QString::fromLatin1("http://example.com/")); + QCOMPARE(name.localName(np2), QString::fromLatin1("localName")); + QCOMPARE(name.prefix(np2), QString::fromLatin1("prefix")); +} + +void tst_QXmlSchema::networkAccessManagerSignature() const +{ + /* Const object. */ + const QXmlSchema schema; + + /* The function should be const. */ + schema.networkAccessManager(); +} + +void tst_QXmlSchema::networkAccessManagerDefaultValue() const +{ + /* Test that the default value of network access manager is not empty. */ + { + QXmlSchema schema; + QVERIFY(schema.networkAccessManager() != static_cast(0)); + } +} + +void tst_QXmlSchema::networkAccessManager() const +{ + /* Test that we return the network manager that was set. */ + { + QNetworkAccessManager manager; + QXmlSchema schema; + schema.setNetworkAccessManager(&manager); + QCOMPARE(schema.networkAccessManager(), &manager); + } +} + +void tst_QXmlSchema::messageHandlerSignature() const +{ + /* Const object. */ + const QXmlSchema schema; + + /* The function should be const. */ + schema.messageHandler(); +} + +void tst_QXmlSchema::messageHandlerDefaultValue() const +{ + /* Test that the default value of message handler is not empty. */ + { + QXmlSchema schema; + QVERIFY(schema.messageHandler() != static_cast(0)); + } +} + +void tst_QXmlSchema::messageHandler() const +{ + /* Test that we return the message handler that was set. */ + { + DummyMessageHandler handler; + + QXmlSchema schema; + schema.setMessageHandler(&handler); + QCOMPARE(schema.messageHandler(), &handler); + } +} + +void tst_QXmlSchema::uriResolverSignature() const +{ + /* Const object. */ + const QXmlSchema schema; + + /* The function should be const. */ + schema.uriResolver(); +} + +void tst_QXmlSchema::uriResolverDefaultValue() const +{ + /* Test that the default value of uri resolver is empty. */ + { + QXmlSchema schema; + QVERIFY(schema.uriResolver() == static_cast(0)); + } +} + +void tst_QXmlSchema::uriResolver() const +{ + /* Test that we return the uri resolver that was set. */ + { + DummyUriResolver resolver; + + QXmlSchema schema; + schema.setUriResolver(&resolver); + QCOMPARE(schema.uriResolver(), &resolver); + } +} + +QTEST_MAIN(tst_QXmlSchema) + +#include "tst_qxmlschema.moc" +#else //QTEST_PATTERNIST +QTEST_NOOP_MAIN +#endif diff --git a/tests/auto/qxmlschemavalidator/.gitignore b/tests/auto/qxmlschemavalidator/.gitignore new file mode 100644 index 0000000..8857212 --- /dev/null +++ b/tests/auto/qxmlschemavalidator/.gitignore @@ -0,0 +1 @@ +tst_qxmlschemavalidator diff --git a/tests/auto/qxmlschemavalidator/qxmlschemavalidator.pro b/tests/auto/qxmlschemavalidator/qxmlschemavalidator.pro new file mode 100644 index 0000000..88ef317 --- /dev/null +++ b/tests/auto/qxmlschemavalidator/qxmlschemavalidator.pro @@ -0,0 +1,4 @@ +load(qttest_p4) +SOURCES += tst_qxmlschemavalidator.cpp + +include (../xmlpatterns.pri) diff --git a/tests/auto/qxmlschemavalidator/tst_qxmlschemavalidator.cpp b/tests/auto/qxmlschemavalidator/tst_qxmlschemavalidator.cpp new file mode 100644 index 0000000..b021b08 --- /dev/null +++ b/tests/auto/qxmlschemavalidator/tst_qxmlschemavalidator.cpp @@ -0,0 +1,308 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +****************************************************************************/ + +#include + +#ifdef QTEST_XMLPATTERNS + +#include +#include +#include +#include +#include +#include + +class DummyMessageHandler : public QAbstractMessageHandler +{ + public: + DummyMessageHandler(QObject *parent = 0) + : QAbstractMessageHandler(parent) + { + } + + protected: + virtual void handleMessage(QtMsgType, const QString&, const QUrl&, const QSourceLocation&) + { + } +}; + +class DummyUriResolver : public QAbstractUriResolver +{ + public: + DummyUriResolver(QObject *parent = 0) + : QAbstractUriResolver(parent) + { + } + + virtual QUrl resolve(const QUrl&, const QUrl&) const + { + return QUrl(); + } +}; + +/*! + \class tst_QXmlSchemaValidatorValidator + \internal + \brief Tests class QXmlSchemaValidator. + + This test is not intended for testing the engine, but the functionality specific + to the QXmlSchemaValidator class. + */ +class tst_QXmlSchemaValidator : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void defaultConstructor() const; + void propertyInitialization() const; + + void networkAccessManagerSignature() const; + void networkAccessManagerDefaultValue() const; + void networkAccessManager() const; + + void messageHandlerSignature() const; + void messageHandlerDefaultValue() const; + void messageHandler() const; + + void uriResolverSignature() const; + void uriResolverDefaultValue() const; + void uriResolver() const; +}; + +void tst_QXmlSchemaValidator::defaultConstructor() const +{ + /* Allocate instance in different orders. */ + { + QXmlSchema schema; + QXmlSchemaValidator validator(schema); + } + + { + QXmlSchema schema1; + QXmlSchema schema2; + + QXmlSchemaValidator validator1(schema1); + QXmlSchemaValidator validator2(schema2); + } + + { + QXmlSchema schema; + + QXmlSchemaValidator validator1(schema); + QXmlSchemaValidator validator2(schema); + } +} + +void tst_QXmlSchemaValidator::propertyInitialization() const +{ + /* Verify that properties set in the schema are used as default values for the validator */ + { + DummyMessageHandler handler; + DummyUriResolver resolver; + QNetworkAccessManager manager; + + QXmlSchema schema; + schema.setMessageHandler(&handler); + schema.setUriResolver(&resolver); + schema.setNetworkAccessManager(&manager); + + QXmlSchemaValidator validator(schema); + QCOMPARE(validator.messageHandler(), &handler); + QCOMPARE(validator.uriResolver(), &resolver); + QCOMPARE(validator.networkAccessManager(), &manager); + } +} + +void tst_QXmlSchemaValidator::networkAccessManagerSignature() const +{ + const QXmlSchema schema; + + /* Const object. */ + const QXmlSchemaValidator validator(schema); + + /* The function should be const. */ + validator.networkAccessManager(); +} + +void tst_QXmlSchemaValidator::networkAccessManagerDefaultValue() const +{ + /* Test that the default value of network access manager is equal to the one from the schema. */ + { + const QXmlSchema schema; + const QXmlSchemaValidator validator(schema); + QVERIFY(validator.networkAccessManager() == schema.networkAccessManager()); + } + + /* Test that the default value of network access manager is equal to the one from the schema. */ + { + QXmlSchema schema; + + QNetworkAccessManager manager; + schema.setNetworkAccessManager(&manager); + + const QXmlSchemaValidator validator(schema); + QVERIFY(validator.networkAccessManager() == schema.networkAccessManager()); + } +} + +void tst_QXmlSchemaValidator::networkAccessManager() const +{ + /* Test that we return the network access manager that was set. */ + { + QNetworkAccessManager manager; + + const QXmlSchema schema; + QXmlSchemaValidator validator(schema); + + validator.setNetworkAccessManager(&manager); + QCOMPARE(validator.networkAccessManager(), &manager); + } + + /* Test that we return the network access manager that was set, even if the schema changed in between. */ + { + QNetworkAccessManager manager; + + const QXmlSchema schema; + QXmlSchemaValidator validator(schema); + + validator.setNetworkAccessManager(&manager); + + const QXmlSchema schema2; + validator.setSchema(schema2); + + QCOMPARE(validator.networkAccessManager(), &manager); + } +} + +void tst_QXmlSchemaValidator::messageHandlerSignature() const +{ + const QXmlSchema schema; + + /* Const object. */ + const QXmlSchemaValidator validator(schema); + + /* The function should be const. */ + validator.messageHandler(); +} + +void tst_QXmlSchemaValidator::messageHandlerDefaultValue() const +{ + /* Test that the default value of message handler is equal to the one from the schema. */ + { + const QXmlSchema schema; + const QXmlSchemaValidator validator(schema); + QVERIFY(validator.messageHandler() == schema.messageHandler()); + } + + /* Test that the default value of network access manager is equal to the one from the schema. */ + { + QXmlSchema schema; + + DummyMessageHandler handler; + schema.setMessageHandler(&handler); + + const QXmlSchemaValidator validator(schema); + QVERIFY(validator.messageHandler() == schema.messageHandler()); + } +} + +void tst_QXmlSchemaValidator::messageHandler() const +{ + /* Test that we return the message handler that was set. */ + { + DummyMessageHandler handler; + + const QXmlSchema schema; + QXmlSchemaValidator validator(schema); + + validator.setMessageHandler(&handler); + QCOMPARE(validator.messageHandler(), &handler); + } + + /* Test that we return the message handler that was set, even if the schema changed in between. */ + { + DummyMessageHandler handler; + + const QXmlSchema schema; + QXmlSchemaValidator validator(schema); + + validator.setMessageHandler(&handler); + + const QXmlSchema schema2; + validator.setSchema(schema2); + + QCOMPARE(validator.messageHandler(), &handler); + } +} + +void tst_QXmlSchemaValidator::uriResolverSignature() const +{ + const QXmlSchema schema; + + /* Const object. */ + const QXmlSchemaValidator validator(schema); + + /* The function should be const. */ + validator.uriResolver(); +} + +void tst_QXmlSchemaValidator::uriResolverDefaultValue() const +{ + /* Test that the default value of uri resolver is equal to the one from the schema. */ + { + const QXmlSchema schema; + const QXmlSchemaValidator validator(schema); + QVERIFY(validator.uriResolver() == schema.uriResolver()); + } + + /* Test that the default value of uri resolver is equal to the one from the schema. */ + { + QXmlSchema schema; + + DummyUriResolver resolver; + schema.setUriResolver(&resolver); + + const QXmlSchemaValidator validator(schema); + QVERIFY(validator.uriResolver() == schema.uriResolver()); + } +} + +void tst_QXmlSchemaValidator::uriResolver() const +{ + /* Test that we return the uri resolver that was set. */ + { + DummyUriResolver resolver; + + const QXmlSchema schema; + QXmlSchemaValidator validator(schema); + + validator.setUriResolver(&resolver); + QCOMPARE(validator.uriResolver(), &resolver); + } + + /* Test that we return the uri resolver that was set, even if the schema changed in between. */ + { + DummyUriResolver resolver; + + const QXmlSchema schema; + QXmlSchemaValidator validator(schema); + + validator.setUriResolver(&resolver); + + const QXmlSchema schema2; + validator.setSchema(schema2); + + QCOMPARE(validator.uriResolver(), &resolver); + } +} + +QTEST_MAIN(tst_QXmlSchemaValidator) + +#include "tst_qxmlschemavalidator.moc" +#else //QTEST_PATTERNIST +QTEST_NOOP_MAIN +#endif diff --git a/tests/auto/runQtXmlPatternsTests.sh b/tests/auto/runQtXmlPatternsTests.sh index 49ea840..41d6c83 100755 --- a/tests/auto/runQtXmlPatternsTests.sh +++ b/tests/auto/runQtXmlPatternsTests.sh @@ -34,6 +34,8 @@ qxmlserializer \ xmlpatterns \ xmlpatternsxqts \ xmlpatternsdiagnosticsts \ +xmlpatternsschema \ +xmlpatternsschemats \ xmlpatternsview \ xmlpatternsxslts" diff --git a/tests/auto/xmlpatterns.pri b/tests/auto/xmlpatterns.pri index bf13c3b..7cdd67f 100644 --- a/tests/auto/xmlpatterns.pri +++ b/tests/auto/xmlpatterns.pri @@ -19,3 +19,17 @@ if(!debug_and_release|build_pass):CONFIG(debug, debug|release) { else: XMLPATTERNS_SDK = $${XMLPATTERNS_SDK}_debug } +INCLUDEPATH += \ + $$QT_SOURCE_TREE/src/xmlpatterns/acceltree \ + $$QT_SOURCE_TREE/src/xmlpatterns/api \ + $$QT_SOURCE_TREE/src/xmlpatterns/data \ + $$QT_SOURCE_TREE/src/xmlpatterns/environment \ + $$QT_SOURCE_TREE/src/xmlpatterns/expr \ + $$QT_SOURCE_TREE/src/xmlpatterns/functions \ + $$QT_SOURCE_TREE/src/xmlpatterns/iterators \ + $$QT_SOURCE_TREE/src/xmlpatterns/janitors \ + $$QT_SOURCE_TREE/src/xmlpatterns/parser \ + $$QT_SOURCE_TREE/src/xmlpatterns/projection \ + $$QT_SOURCE_TREE/src/xmlpatterns/schema \ + $$QT_SOURCE_TREE/src/xmlpatterns/type \ + $$QT_SOURCE_TREE/src/xmlpatterns/utils diff --git a/tests/auto/xmlpatternsdiagnosticsts/test/tst_xmlpatternsdiagnosticsts.cpp b/tests/auto/xmlpatternsdiagnosticsts/test/tst_xmlpatternsdiagnosticsts.cpp index 60037f9..13c3534 100644 --- a/tests/auto/xmlpatternsdiagnosticsts/test/tst_xmlpatternsdiagnosticsts.cpp +++ b/tests/auto/xmlpatternsdiagnosticsts/test/tst_xmlpatternsdiagnosticsts.cpp @@ -61,7 +61,7 @@ protected: virtual void catalogPath(QString &write) const; }; -tst_XmlPatternsXSLTS::tst_XmlPatternsXSLTS() : tst_SuiteTest(false, true) +tst_XmlPatternsXSLTS::tst_XmlPatternsXSLTS() : tst_SuiteTest(tst_SuiteTest::XQuerySuite, true) { } diff --git a/tests/auto/xmlpatternsschema/.gitignore b/tests/auto/xmlpatternsschema/.gitignore new file mode 100644 index 0000000..a37a2b7 --- /dev/null +++ b/tests/auto/xmlpatternsschema/.gitignore @@ -0,0 +1 @@ +tst_xmlpatternsschema diff --git a/tests/auto/xmlpatternsschema/tst_xmlpatternsschema.cpp b/tests/auto/xmlpatternsschema/tst_xmlpatternsschema.cpp new file mode 100644 index 0000000..030e9c0 --- /dev/null +++ b/tests/auto/xmlpatternsschema/tst_xmlpatternsschema.cpp @@ -0,0 +1,988 @@ + +#include + +#include "qxsdstatemachine_p.h" +#include "qxsdschematoken_p.h" + +using namespace QPatternist; + +class tst_XMLPatternsSchema : public QObject +{ + Q_OBJECT + + public slots: + void init(); + void cleanup(); + + private slots: + void stateMachineTest1(); + void stateMachineTest2(); + void stateMachineTest3(); + void stateMachineTest4(); + void stateMachineTest5(); + void stateMachineTest6(); + void stateMachineTest7(); + void stateMachineTest8(); + void stateMachineTest9(); + void stateMachineTest10(); + void stateMachineTest11(); + void stateMachineTest12(); + void stateMachineTest13(); + void stateMachineTest14(); + void stateMachineTest15(); + void stateMachineTest16(); + void stateMachineTest17(); + void stateMachineTest18(); + void stateMachineTest19(); + + private: + bool runTest(const QVector &list, XsdStateMachine &machine); +}; + +void tst_XMLPatternsSchema::init() +{ +} + +void tst_XMLPatternsSchema::cleanup() +{ +} + +bool tst_XMLPatternsSchema::runTest(const QVector &list, XsdStateMachine &machine) +{ + machine.reset(); + for (int i = 0; i < list.count(); ++i) { + if (!machine.proceed(list.at(i))) + return false; + } + if (!machine.inEndState()) + return false; + + return true; +} + +void tst_XMLPatternsSchema::stateMachineTest1() +{ + XsdStateMachine machine; + + // setup state machine for (annotation?, simpleType?) : attribute + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Annotation, s1); + machine.addTransition(startState, XsdSchemaToken::SimpleType, s2); + machine.addTransition(s1, XsdSchemaToken::SimpleType, s2); + + QVERIFY(machine.inEndState() == true); + QVERIFY(machine.proceed(XsdSchemaToken::Annotation) == true); + QVERIFY(machine.inEndState() == true); + QVERIFY(machine.proceed(XsdSchemaToken::SimpleType) == true); + QVERIFY(machine.inEndState() == true); + QVERIFY(machine.proceed(XsdSchemaToken::SimpleType) == false); + QVERIFY(machine.proceed(XsdSchemaToken::Annotation) == false); + machine.reset(); + QVERIFY(machine.proceed(XsdSchemaToken::SimpleType) == true); + QVERIFY(machine.inEndState() == true); + QVERIFY(machine.proceed(XsdSchemaToken::Annotation) == false); +} + +void tst_XMLPatternsSchema::stateMachineTest2() +{ + XsdStateMachine machine; + + // setup state machine for (annotation?, ((simpleType | complexType)?, (unique | key | keyref)*)) : element + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s3 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s4 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s5 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s6 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Annotation, s1); + machine.addTransition(startState, XsdSchemaToken::SimpleType, s2); + machine.addTransition(startState, XsdSchemaToken::ComplexType, s3); + machine.addTransition(startState, XsdSchemaToken::Unique, s4); + machine.addTransition(startState, XsdSchemaToken::Key, s5); + machine.addTransition(startState, XsdSchemaToken::Keyref, s6); + + machine.addTransition(s1, XsdSchemaToken::SimpleType, s2); + machine.addTransition(s1, XsdSchemaToken::ComplexType, s3); + machine.addTransition(s1, XsdSchemaToken::Unique, s4); + machine.addTransition(s1, XsdSchemaToken::Key, s5); + machine.addTransition(s1, XsdSchemaToken::Keyref, s6); + + machine.addTransition(s2, XsdSchemaToken::Unique, s4); + machine.addTransition(s2, XsdSchemaToken::Key, s5); + machine.addTransition(s2, XsdSchemaToken::Keyref, s6); + + machine.addTransition(s3, XsdSchemaToken::Unique, s4); + machine.addTransition(s3, XsdSchemaToken::Key, s5); + machine.addTransition(s3, XsdSchemaToken::Keyref, s6); + + machine.addTransition(s4, XsdSchemaToken::Unique, s4); + machine.addTransition(s4, XsdSchemaToken::Key, s5); + machine.addTransition(s4, XsdSchemaToken::Keyref, s6); + + machine.addTransition(s5, XsdSchemaToken::Unique, s4); + machine.addTransition(s5, XsdSchemaToken::Key, s5); + machine.addTransition(s5, XsdSchemaToken::Keyref, s6); + + machine.addTransition(s6, XsdSchemaToken::Unique, s4); + machine.addTransition(s6, XsdSchemaToken::Key, s5); + machine.addTransition(s6, XsdSchemaToken::Keyref, s6); + + QVector data1, data2, data3; + + data1 << XsdSchemaToken::Annotation + << XsdSchemaToken::SimpleType + << XsdSchemaToken::Unique + << XsdSchemaToken::Keyref; + + data2 << XsdSchemaToken::Annotation + << XsdSchemaToken::SimpleType + << XsdSchemaToken::Annotation + << XsdSchemaToken::Keyref; + + data3 << XsdSchemaToken::Annotation + << XsdSchemaToken::SimpleType + << XsdSchemaToken::SimpleType; + + QVERIFY(runTest(data1, machine) == true); + QVERIFY(runTest(data2, machine) == false); + QVERIFY(runTest(data3, machine) == false); +} + +void tst_XMLPatternsSchema::stateMachineTest3() +{ + XsdStateMachine machine; + + // setup state machine for (annotation?, (simpleContent | complexContent | ((group | all | choice | sequence)?, ((attribute | attributeGroup)*, anyAttribute?)))) : complexType + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s3 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s4 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s5 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s6 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s7 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s8 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s9 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s10 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Annotation, s1); + machine.addTransition(startState, XsdSchemaToken::SimpleContent, s2); + machine.addTransition(startState, XsdSchemaToken::ComplexContent, s3); + machine.addTransition(startState, XsdSchemaToken::Group, s4); + machine.addTransition(startState, XsdSchemaToken::All, s5); + machine.addTransition(startState, XsdSchemaToken::Choice, s6); + machine.addTransition(startState, XsdSchemaToken::Sequence, s7); + machine.addTransition(startState, XsdSchemaToken::Attribute, s8); + machine.addTransition(startState, XsdSchemaToken::AttributeGroup, s9); + machine.addTransition(startState, XsdSchemaToken::AnyAttribute, s10); + + machine.addTransition(s1, XsdSchemaToken::SimpleContent, s2); + machine.addTransition(s1, XsdSchemaToken::ComplexContent, s3); + machine.addTransition(s1, XsdSchemaToken::Group, s4); + machine.addTransition(s1, XsdSchemaToken::All, s5); + machine.addTransition(s1, XsdSchemaToken::Choice, s6); + machine.addTransition(s1, XsdSchemaToken::Sequence, s7); + machine.addTransition(s1, XsdSchemaToken::Attribute, s8); + machine.addTransition(s1, XsdSchemaToken::AttributeGroup, s9); + machine.addTransition(s1, XsdSchemaToken::AnyAttribute, s10); + + machine.addTransition(s4, XsdSchemaToken::Attribute, s8); + machine.addTransition(s4, XsdSchemaToken::AttributeGroup, s9); + machine.addTransition(s4, XsdSchemaToken::AnyAttribute, s10); + + machine.addTransition(s5, XsdSchemaToken::Attribute, s8); + machine.addTransition(s5, XsdSchemaToken::AttributeGroup, s9); + machine.addTransition(s5, XsdSchemaToken::AnyAttribute, s10); + + machine.addTransition(s6, XsdSchemaToken::Attribute, s8); + machine.addTransition(s6, XsdSchemaToken::AttributeGroup, s9); + machine.addTransition(s6, XsdSchemaToken::AnyAttribute, s10); + + machine.addTransition(s7, XsdSchemaToken::Attribute, s8); + machine.addTransition(s7, XsdSchemaToken::AttributeGroup, s9); + machine.addTransition(s7, XsdSchemaToken::AnyAttribute, s10); + + machine.addTransition(s8, XsdSchemaToken::Attribute, s8); + machine.addTransition(s8, XsdSchemaToken::AttributeGroup, s9); + machine.addTransition(s8, XsdSchemaToken::AnyAttribute, s10); + + QVector data1, data2, data3, data4; + + data1 << XsdSchemaToken::Annotation + << XsdSchemaToken::SimpleContent; + + data2 << XsdSchemaToken::Group + << XsdSchemaToken::Attribute + << XsdSchemaToken::Attribute + << XsdSchemaToken::AnyAttribute; + + data3 << XsdSchemaToken::Group + << XsdSchemaToken::Choice + << XsdSchemaToken::Attribute + << XsdSchemaToken::AnyAttribute; + + data4 << XsdSchemaToken::Annotation + << XsdSchemaToken::Sequence + << XsdSchemaToken::AnyAttribute; + + QVERIFY(runTest(data1, machine) == true); + QVERIFY(runTest(data2, machine) == true); + QVERIFY(runTest(data3, machine) == false); + QVERIFY(runTest(data4, machine) == true); +} + +void tst_XMLPatternsSchema::stateMachineTest4() +{ + XsdStateMachine machine; + + // setup state machine for (annotation?, ((attribute | attributeGroup)*, anyAttribute?)) : named attribute group/simple content extension/ + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s3 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s4 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Annotation, s1); + machine.addTransition(startState, XsdSchemaToken::Attribute, s2); + machine.addTransition(startState, XsdSchemaToken::AttributeGroup, s3); + machine.addTransition(startState, XsdSchemaToken::AnyAttribute, s4); + + machine.addTransition(s1, XsdSchemaToken::Attribute, s2); + machine.addTransition(s1, XsdSchemaToken::AttributeGroup, s3); + machine.addTransition(s1, XsdSchemaToken::AnyAttribute, s4); + + machine.addTransition(s2, XsdSchemaToken::Attribute, s2); + machine.addTransition(s2, XsdSchemaToken::AttributeGroup, s3); + machine.addTransition(s2, XsdSchemaToken::AnyAttribute, s4); + + machine.addTransition(s3, XsdSchemaToken::Attribute, s2); + machine.addTransition(s3, XsdSchemaToken::AttributeGroup, s3); + machine.addTransition(s3, XsdSchemaToken::AnyAttribute, s4); + + QVector data1, data2, data3, data4; + + data1 << XsdSchemaToken::Annotation; + + data2 << XsdSchemaToken::Attribute + << XsdSchemaToken::Attribute + << XsdSchemaToken::Attribute + << XsdSchemaToken::AnyAttribute; + + data3 << XsdSchemaToken::Group + << XsdSchemaToken::Attribute + << XsdSchemaToken::AnyAttribute; + + data4 << XsdSchemaToken::Attribute + << XsdSchemaToken::AnyAttribute + << XsdSchemaToken::Attribute; + + QVERIFY(runTest(data1, machine) == true); + QVERIFY(runTest(data2, machine) == true); + QVERIFY(runTest(data3, machine) == false); + QVERIFY(runTest(data4, machine) == false); +} + +void tst_XMLPatternsSchema::stateMachineTest5() +{ + XsdStateMachine machine; + + // setup state machine for (annotation?, (all | choice | sequence)?) : group + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s3 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s4 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Annotation, s1); + machine.addTransition(startState, XsdSchemaToken::All, s2); + machine.addTransition(startState, XsdSchemaToken::Choice, s3); + machine.addTransition(startState, XsdSchemaToken::Sequence, s4); + + machine.addTransition(s1, XsdSchemaToken::All, s2); + machine.addTransition(s1, XsdSchemaToken::Choice, s3); + machine.addTransition(s1, XsdSchemaToken::Sequence, s4); + + QVector data1, data2, data3, data4, data5, data6, data7, data8, data9; + + data1 << XsdSchemaToken::Annotation; + data2 << XsdSchemaToken::Annotation << XsdSchemaToken::All; + data3 << XsdSchemaToken::Annotation << XsdSchemaToken::Choice; + data4 << XsdSchemaToken::Annotation << XsdSchemaToken::Sequence; + data5 << XsdSchemaToken::All; + data6 << XsdSchemaToken::Choice; + data7 << XsdSchemaToken::Sequence; + data8 << XsdSchemaToken::Sequence << XsdSchemaToken::All; + + QVERIFY(runTest(data1, machine) == true); + QVERIFY(runTest(data2, machine) == true); + QVERIFY(runTest(data3, machine) == true); + QVERIFY(runTest(data4, machine) == true); + QVERIFY(runTest(data5, machine) == true); + QVERIFY(runTest(data6, machine) == true); + QVERIFY(runTest(data7, machine) == true); + QVERIFY(runTest(data8, machine) == false); + QVERIFY(runTest(data9, machine) == true); +} + +void tst_XMLPatternsSchema::stateMachineTest6() +{ + XsdStateMachine machine; + + // setup state machine for (annotation?, element*) : all + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Annotation, s1); + machine.addTransition(startState, XsdSchemaToken::Element, s2); + + machine.addTransition(s1, XsdSchemaToken::Element, s2); + + machine.addTransition(s2, XsdSchemaToken::Element, s2); + + QVector data1, data2, data3, data4, data5, data6, data7, data8, data9; + + data1 << XsdSchemaToken::Annotation; + data2 << XsdSchemaToken::Annotation << XsdSchemaToken::Element; + data3 << XsdSchemaToken::Element; + data4 << XsdSchemaToken::Element << XsdSchemaToken::Sequence; + data5 << XsdSchemaToken::Annotation << XsdSchemaToken::Element << XsdSchemaToken::Annotation; + data6 << XsdSchemaToken::Annotation << XsdSchemaToken::Annotation << XsdSchemaToken::Element; + + QVERIFY(runTest(data1, machine) == true); + QVERIFY(runTest(data2, machine) == true); + QVERIFY(runTest(data3, machine) == true); + QVERIFY(runTest(data4, machine) == false); + QVERIFY(runTest(data5, machine) == false); + QVERIFY(runTest(data6, machine) == false); +} + +void tst_XMLPatternsSchema::stateMachineTest7() +{ + XsdStateMachine machine; + + // setup state machine for (annotation?, (element | group | choice | sequence | any)*) : choice sequence + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s3 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s4 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s5 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s6 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Annotation, s1); + machine.addTransition(startState, XsdSchemaToken::Element, s2); + machine.addTransition(startState, XsdSchemaToken::Group, s3); + machine.addTransition(startState, XsdSchemaToken::Choice, s4); + machine.addTransition(startState, XsdSchemaToken::Sequence, s5); + machine.addTransition(startState, XsdSchemaToken::Any, s6); + + machine.addTransition(s1, XsdSchemaToken::Element, s2); + machine.addTransition(s1, XsdSchemaToken::Group, s3); + machine.addTransition(s1, XsdSchemaToken::Choice, s4); + machine.addTransition(s1, XsdSchemaToken::Sequence, s5); + machine.addTransition(s1, XsdSchemaToken::Any, s6); + + machine.addTransition(s2, XsdSchemaToken::Element, s2); + machine.addTransition(s2, XsdSchemaToken::Group, s3); + machine.addTransition(s2, XsdSchemaToken::Choice, s4); + machine.addTransition(s2, XsdSchemaToken::Sequence, s5); + machine.addTransition(s2, XsdSchemaToken::Any, s6); + + machine.addTransition(s3, XsdSchemaToken::Element, s2); + machine.addTransition(s3, XsdSchemaToken::Group, s3); + machine.addTransition(s3, XsdSchemaToken::Choice, s4); + machine.addTransition(s3, XsdSchemaToken::Sequence, s5); + machine.addTransition(s3, XsdSchemaToken::Any, s6); + + machine.addTransition(s4, XsdSchemaToken::Element, s2); + machine.addTransition(s4, XsdSchemaToken::Group, s3); + machine.addTransition(s4, XsdSchemaToken::Choice, s4); + machine.addTransition(s4, XsdSchemaToken::Sequence, s5); + machine.addTransition(s4, XsdSchemaToken::Any, s6); + + machine.addTransition(s5, XsdSchemaToken::Element, s2); + machine.addTransition(s5, XsdSchemaToken::Group, s3); + machine.addTransition(s5, XsdSchemaToken::Choice, s4); + machine.addTransition(s5, XsdSchemaToken::Sequence, s5); + machine.addTransition(s5, XsdSchemaToken::Any, s6); + + machine.addTransition(s6, XsdSchemaToken::Element, s2); + machine.addTransition(s6, XsdSchemaToken::Group, s3); + machine.addTransition(s6, XsdSchemaToken::Choice, s4); + machine.addTransition(s6, XsdSchemaToken::Sequence, s5); + machine.addTransition(s6, XsdSchemaToken::Any, s6); + + QVector data1, data2, data3, data4, data5, data6, data7, data8, data9; + + data1 << XsdSchemaToken::Annotation; + data2 << XsdSchemaToken::Annotation << XsdSchemaToken::Element << XsdSchemaToken::Sequence << XsdSchemaToken::Choice; + data3 << XsdSchemaToken::Group; + data4 << XsdSchemaToken::Element << XsdSchemaToken::Sequence << XsdSchemaToken::Annotation; + + QVERIFY(runTest(data1, machine) == true); + QVERIFY(runTest(data2, machine) == true); + QVERIFY(runTest(data3, machine) == true); + QVERIFY(runTest(data4, machine) == false); +} + +void tst_XMLPatternsSchema::stateMachineTest8() +{ + XsdStateMachine machine; + + // setup state machine for (annotation?) : any/selector/field/notation/include/import/referred attribute group/anyAttribute/all facets + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Annotation, s1); + + QVector data1, data2, data3, data4; + + data1 << XsdSchemaToken::Annotation; + data2 << XsdSchemaToken::Annotation << XsdSchemaToken::Element; + data3 << XsdSchemaToken::Group; + + QVERIFY(runTest(data1, machine) == true); + QVERIFY(runTest(data2, machine) == false); + QVERIFY(runTest(data3, machine) == false); + QVERIFY(runTest(data4, machine) == true); +} + +void tst_XMLPatternsSchema::stateMachineTest9() +{ + XsdStateMachine machine; + + // setup state machine for (annotation?, (selector, field+)) : unique/key/keyref + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::InternalState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::InternalState); + const XsdStateMachine::StateId s3 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Annotation, s1); + machine.addTransition(startState, XsdSchemaToken::Selector, s2); + + machine.addTransition(s1, XsdSchemaToken::Selector, s2); + machine.addTransition(s2, XsdSchemaToken::Field, s3); + machine.addTransition(s3, XsdSchemaToken::Field, s3); + + QVector data1, data2, data3, data4, data5; + + data1 << XsdSchemaToken::Annotation; + data2 << XsdSchemaToken::Annotation << XsdSchemaToken::Selector; + data3 << XsdSchemaToken::Annotation << XsdSchemaToken::Selector << XsdSchemaToken::Field; + data4 << XsdSchemaToken::Selector << XsdSchemaToken::Field; + data5 << XsdSchemaToken::Selector << XsdSchemaToken::Field << XsdSchemaToken::Field; + + QVERIFY(runTest(data1, machine) == false); + QVERIFY(runTest(data2, machine) == false); + QVERIFY(runTest(data3, machine) == true); + QVERIFY(runTest(data4, machine) == true); + QVERIFY(runTest(data5, machine) == true); +} + +void tst_XMLPatternsSchema::stateMachineTest10() +{ + XsdStateMachine machine; + + // setup state machine for (appinfo | documentation)* : annotation + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Appinfo, s1); + machine.addTransition(startState, XsdSchemaToken::Documentation, s2); + + machine.addTransition(s1, XsdSchemaToken::Appinfo, s1); + machine.addTransition(s1, XsdSchemaToken::Documentation, s2); + + machine.addTransition(s2, XsdSchemaToken::Appinfo, s1); + machine.addTransition(s2, XsdSchemaToken::Documentation, s2); + + QVector data1, data2, data3, data4, data5; + + data1 << XsdSchemaToken::Appinfo; + data2 << XsdSchemaToken::Appinfo << XsdSchemaToken::Appinfo; + data3 << XsdSchemaToken::Documentation << XsdSchemaToken::Appinfo << XsdSchemaToken::Documentation; + data4 << XsdSchemaToken::Selector << XsdSchemaToken::Field; + + QVERIFY(runTest(data1, machine) == true); + QVERIFY(runTest(data2, machine) == true); + QVERIFY(runTest(data3, machine) == true); + QVERIFY(runTest(data4, machine) == false); + QVERIFY(runTest(data5, machine) == true); +} + +void tst_XMLPatternsSchema::stateMachineTest11() +{ + XsdStateMachine machine; + + // setup state machine for (annotation?, (restriction | list | union)) : simpleType + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::InternalState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s3 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s4 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Annotation, s1); + machine.addTransition(startState, XsdSchemaToken::Restriction, s2); + machine.addTransition(startState, XsdSchemaToken::List, s3); + machine.addTransition(startState, XsdSchemaToken::Union, s4); + + machine.addTransition(s1, XsdSchemaToken::Restriction, s2); + machine.addTransition(s1, XsdSchemaToken::List, s3); + machine.addTransition(s1, XsdSchemaToken::Union, s4); + + QVector data1, data2, data3, data4, data5, data6, data7, data8; + + data1 << XsdSchemaToken::Annotation; + data2 << XsdSchemaToken::Annotation << XsdSchemaToken::Restriction; + data3 << XsdSchemaToken::Annotation << XsdSchemaToken::List; + data4 << XsdSchemaToken::Annotation << XsdSchemaToken::Union; + data5 << XsdSchemaToken::Restriction; + data6 << XsdSchemaToken::List; + data7 << XsdSchemaToken::Union; + data8 << XsdSchemaToken::Union << XsdSchemaToken::Union; + + QVERIFY(runTest(data1, machine) == false); + QVERIFY(runTest(data2, machine) == true); + QVERIFY(runTest(data3, machine) == true); + QVERIFY(runTest(data4, machine) == true); + QVERIFY(runTest(data5, machine) == true); + QVERIFY(runTest(data6, machine) == true); + QVERIFY(runTest(data7, machine) == true); + QVERIFY(runTest(data8, machine) == false); +} + +void tst_XMLPatternsSchema::stateMachineTest12() +{ + XsdStateMachine machine; + + // setup state machine for (annotation?, (simpleType?, (minExclusive | minInclusive | maxExclusive | maxInclusive | totalDigits | fractionDigits | length | minLength | maxLength | enumeration | whiteSpace | pattern)*)) : simple type restriction + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s3 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Annotation, s1); + machine.addTransition(startState, XsdSchemaToken::SimpleType, s2); + machine.addTransition(startState, XsdSchemaToken::MinExclusive, s3); + machine.addTransition(startState, XsdSchemaToken::MinInclusive, s3); + machine.addTransition(startState, XsdSchemaToken::MaxExclusive, s3); + machine.addTransition(startState, XsdSchemaToken::MaxInclusive, s3); + machine.addTransition(startState, XsdSchemaToken::TotalDigits, s3); + machine.addTransition(startState, XsdSchemaToken::FractionDigits, s3); + machine.addTransition(startState, XsdSchemaToken::Length, s3); + machine.addTransition(startState, XsdSchemaToken::MinLength, s3); + machine.addTransition(startState, XsdSchemaToken::MaxLength, s3); + machine.addTransition(startState, XsdSchemaToken::Enumeration, s3); + machine.addTransition(startState, XsdSchemaToken::WhiteSpace, s3); + machine.addTransition(startState, XsdSchemaToken::Pattern, s3); + + machine.addTransition(s1, XsdSchemaToken::SimpleType, s2); + machine.addTransition(s1, XsdSchemaToken::MinExclusive, s3); + machine.addTransition(s1, XsdSchemaToken::MinInclusive, s3); + machine.addTransition(s1, XsdSchemaToken::MaxExclusive, s3); + machine.addTransition(s1, XsdSchemaToken::MaxInclusive, s3); + machine.addTransition(s1, XsdSchemaToken::TotalDigits, s3); + machine.addTransition(s1, XsdSchemaToken::FractionDigits, s3); + machine.addTransition(s1, XsdSchemaToken::Length, s3); + machine.addTransition(s1, XsdSchemaToken::MinLength, s3); + machine.addTransition(s1, XsdSchemaToken::MaxLength, s3); + machine.addTransition(s1, XsdSchemaToken::Enumeration, s3); + machine.addTransition(s1, XsdSchemaToken::WhiteSpace, s3); + machine.addTransition(s1, XsdSchemaToken::Pattern, s3); + + machine.addTransition(s2, XsdSchemaToken::MinExclusive, s3); + machine.addTransition(s2, XsdSchemaToken::MinInclusive, s3); + machine.addTransition(s2, XsdSchemaToken::MaxExclusive, s3); + machine.addTransition(s2, XsdSchemaToken::MaxInclusive, s3); + machine.addTransition(s2, XsdSchemaToken::TotalDigits, s3); + machine.addTransition(s2, XsdSchemaToken::FractionDigits, s3); + machine.addTransition(s2, XsdSchemaToken::Length, s3); + machine.addTransition(s2, XsdSchemaToken::MinLength, s3); + machine.addTransition(s2, XsdSchemaToken::MaxLength, s3); + machine.addTransition(s2, XsdSchemaToken::Enumeration, s3); + machine.addTransition(s2, XsdSchemaToken::WhiteSpace, s3); + machine.addTransition(s2, XsdSchemaToken::Pattern, s3); + + machine.addTransition(s3, XsdSchemaToken::MinExclusive, s3); + machine.addTransition(s3, XsdSchemaToken::MinInclusive, s3); + machine.addTransition(s3, XsdSchemaToken::MaxExclusive, s3); + machine.addTransition(s3, XsdSchemaToken::MaxInclusive, s3); + machine.addTransition(s3, XsdSchemaToken::TotalDigits, s3); + machine.addTransition(s3, XsdSchemaToken::FractionDigits, s3); + machine.addTransition(s3, XsdSchemaToken::Length, s3); + machine.addTransition(s3, XsdSchemaToken::MinLength, s3); + machine.addTransition(s3, XsdSchemaToken::MaxLength, s3); + machine.addTransition(s3, XsdSchemaToken::Enumeration, s3); + machine.addTransition(s3, XsdSchemaToken::WhiteSpace, s3); + machine.addTransition(s3, XsdSchemaToken::Pattern, s3); + + QVector data1, data2, data3, data4, data5; + + data1 << XsdSchemaToken::Annotation; + data2 << XsdSchemaToken::Annotation << XsdSchemaToken::Length << XsdSchemaToken::MaxLength; + data3 << XsdSchemaToken::Annotation << XsdSchemaToken::List; + data4 << XsdSchemaToken::SimpleType << XsdSchemaToken::Pattern; + + QVERIFY(runTest(data1, machine) == true); + QVERIFY(runTest(data2, machine) == true); + QVERIFY(runTest(data3, machine) == false); + QVERIFY(runTest(data4, machine) == true); + QVERIFY(runTest(data5, machine) == true); +} + +void tst_XMLPatternsSchema::stateMachineTest13() +{ + XsdStateMachine machine; + + // setup state machine for (annotation?, simpleType?) : list + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Annotation, s1); + machine.addTransition(startState, XsdSchemaToken::SimpleType, s2); + + machine.addTransition(s1, XsdSchemaToken::SimpleType, s2); + + QVector data1, data2, data3, data4, data5; + + data1 << XsdSchemaToken::Annotation; + data2 << XsdSchemaToken::Annotation << XsdSchemaToken::SimpleType; + data3 << XsdSchemaToken::SimpleType; + data4 << XsdSchemaToken::SimpleType << XsdSchemaToken::SimpleType; + + QVERIFY(runTest(data1, machine) == true); + QVERIFY(runTest(data2, machine) == true); + QVERIFY(runTest(data3, machine) == true); + QVERIFY(runTest(data4, machine) == false); + QVERIFY(runTest(data5, machine) == true); +} + +void tst_XMLPatternsSchema::stateMachineTest14() +{ + XsdStateMachine machine; + + // setup state machine for (annotation?, simpleType*) : union + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Annotation, s1); + machine.addTransition(startState, XsdSchemaToken::SimpleType, s2); + + machine.addTransition(s1, XsdSchemaToken::SimpleType, s2); + machine.addTransition(s2, XsdSchemaToken::SimpleType, s2); + + QVector data1, data2, data3, data4, data5, data6; + + data1 << XsdSchemaToken::Annotation; + data2 << XsdSchemaToken::Annotation << XsdSchemaToken::SimpleType; + data3 << XsdSchemaToken::SimpleType; + data4 << XsdSchemaToken::SimpleType << XsdSchemaToken::SimpleType; + data6 << XsdSchemaToken::Annotation << XsdSchemaToken::Annotation; + + QVERIFY(runTest(data1, machine) == true); + QVERIFY(runTest(data2, machine) == true); + QVERIFY(runTest(data3, machine) == true); + QVERIFY(runTest(data4, machine) == true); + QVERIFY(runTest(data5, machine) == true); + QVERIFY(runTest(data6, machine) == false); +} + +void tst_XMLPatternsSchema::stateMachineTest15() +{ + XsdStateMachine machine; + + // setup state machine for ((include | import | redefine | annotation)*, (((simpleType | complexType | group | attributeGroup) | element | attribute | notation), annotation*)*) : schema + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s3 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Include, s1); + machine.addTransition(startState, XsdSchemaToken::Import, s1); + machine.addTransition(startState, XsdSchemaToken::Redefine, s1); + machine.addTransition(startState, XsdSchemaToken::Annotation, s1); + machine.addTransition(startState, XsdSchemaToken::SimpleType, s2); + machine.addTransition(startState, XsdSchemaToken::ComplexType, s2); + machine.addTransition(startState, XsdSchemaToken::Group, s2); + machine.addTransition(startState, XsdSchemaToken::AttributeGroup, s2); + machine.addTransition(startState, XsdSchemaToken::Element, s2); + machine.addTransition(startState, XsdSchemaToken::Attribute, s2); + machine.addTransition(startState, XsdSchemaToken::Notation, s2); + + machine.addTransition(s1, XsdSchemaToken::Include, s1); + machine.addTransition(s1, XsdSchemaToken::Import, s1); + machine.addTransition(s1, XsdSchemaToken::Redefine, s1); + machine.addTransition(s1, XsdSchemaToken::Annotation, s1); + machine.addTransition(s1, XsdSchemaToken::SimpleType, s2); + machine.addTransition(s1, XsdSchemaToken::ComplexType, s2); + machine.addTransition(s1, XsdSchemaToken::Group, s2); + machine.addTransition(s1, XsdSchemaToken::AttributeGroup, s2); + machine.addTransition(s1, XsdSchemaToken::Element, s2); + machine.addTransition(s1, XsdSchemaToken::Attribute, s2); + machine.addTransition(s1, XsdSchemaToken::Notation, s2); + + machine.addTransition(s2, XsdSchemaToken::SimpleType, s2); + machine.addTransition(s2, XsdSchemaToken::ComplexType, s2); + machine.addTransition(s2, XsdSchemaToken::Group, s2); + machine.addTransition(s2, XsdSchemaToken::AttributeGroup, s2); + machine.addTransition(s2, XsdSchemaToken::Element, s2); + machine.addTransition(s2, XsdSchemaToken::Attribute, s2); + machine.addTransition(s2, XsdSchemaToken::Notation, s2); + machine.addTransition(s2, XsdSchemaToken::Annotation, s3); + + machine.addTransition(s3, XsdSchemaToken::SimpleType, s2); + machine.addTransition(s3, XsdSchemaToken::ComplexType, s2); + machine.addTransition(s3, XsdSchemaToken::Group, s2); + machine.addTransition(s3, XsdSchemaToken::AttributeGroup, s2); + machine.addTransition(s3, XsdSchemaToken::Element, s2); + machine.addTransition(s3, XsdSchemaToken::Attribute, s2); + machine.addTransition(s3, XsdSchemaToken::Notation, s2); + machine.addTransition(s3, XsdSchemaToken::Annotation, s3); + + QVector data1, data2, data3, data4, data5, data6; + + data1 << XsdSchemaToken::Annotation << XsdSchemaToken::Import << XsdSchemaToken::SimpleType << XsdSchemaToken::Annotation; + data2 << XsdSchemaToken::SimpleType; + data3 << XsdSchemaToken::Annotation << XsdSchemaToken::Import << XsdSchemaToken::Include << XsdSchemaToken::Import; + data4 << XsdSchemaToken::SimpleType << XsdSchemaToken::ComplexType << XsdSchemaToken::Annotation << XsdSchemaToken::Attribute; + data5 << XsdSchemaToken::SimpleType << XsdSchemaToken::Include << XsdSchemaToken::Annotation << XsdSchemaToken::Attribute; + + QVERIFY(runTest(data1, machine) == true); + QVERIFY(runTest(data2, machine) == true); + QVERIFY(runTest(data3, machine) == true); + QVERIFY(runTest(data4, machine) == true); + QVERIFY(runTest(data5, machine) == false); + QVERIFY(runTest(data6, machine) == true); +} + +void tst_XMLPatternsSchema::stateMachineTest16() +{ + XsdStateMachine machine; + + // setup state machine for (annotation | (simpleType | complexType | group | attributeGroup))* : redefine + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Annotation, s1); + machine.addTransition(startState, XsdSchemaToken::SimpleType, s1); + machine.addTransition(startState, XsdSchemaToken::ComplexType, s1); + machine.addTransition(startState, XsdSchemaToken::Group, s1); + machine.addTransition(startState, XsdSchemaToken::AttributeGroup, s1); + + machine.addTransition(s1, XsdSchemaToken::Annotation, s1); + machine.addTransition(s1, XsdSchemaToken::SimpleType, s1); + machine.addTransition(s1, XsdSchemaToken::ComplexType, s1); + machine.addTransition(s1, XsdSchemaToken::Group, s1); + machine.addTransition(s1, XsdSchemaToken::AttributeGroup, s1); + + QVector data1, data2, data3, data4, data5, data6; + + data1 << XsdSchemaToken::Annotation; + data2 << XsdSchemaToken::Annotation << XsdSchemaToken::SimpleType; + data3 << XsdSchemaToken::SimpleType; + data4 << XsdSchemaToken::SimpleType << XsdSchemaToken::SimpleType; + data6 << XsdSchemaToken::Annotation << XsdSchemaToken::Annotation; + + QVERIFY(runTest(data1, machine) == true); + QVERIFY(runTest(data2, machine) == true); + QVERIFY(runTest(data3, machine) == true); + QVERIFY(runTest(data4, machine) == true); + QVERIFY(runTest(data5, machine) == true); + QVERIFY(runTest(data6, machine) == true); +} + +void tst_XMLPatternsSchema::stateMachineTest17() +{ + XsdStateMachine machine; + + // setup state machine for (annotation?, (restriction | extension)) : simpleContent + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::InternalState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Annotation, s1); + machine.addTransition(startState, XsdSchemaToken::Restriction, s2); + machine.addTransition(startState, XsdSchemaToken::Extension, s2); + + machine.addTransition(s1, XsdSchemaToken::Restriction, s2); + machine.addTransition(s1, XsdSchemaToken::Extension, s2); + + QVector data1, data2, data3, data4, data5, data6; + + data1 << XsdSchemaToken::Annotation; + data2 << XsdSchemaToken::Annotation << XsdSchemaToken::Extension; + data3 << XsdSchemaToken::Restriction; + data4 << XsdSchemaToken::Extension << XsdSchemaToken::Restriction; + data5 << XsdSchemaToken::Annotation << XsdSchemaToken::Annotation; + + QVERIFY(runTest(data1, machine) == false); + QVERIFY(runTest(data2, machine) == true); + QVERIFY(runTest(data3, machine) == true); + QVERIFY(runTest(data4, machine) == false); + QVERIFY(runTest(data5, machine) == false); + QVERIFY(runTest(data6, machine) == false); +} + +void tst_XMLPatternsSchema::stateMachineTest18() +{ + XsdStateMachine machine; + + // setup state machine for (annotation?, (simpleType?, (minExclusive | minInclusive | maxExclusive | maxInclusive | totalDigits | fractionDigits | length | minLength | maxLength | enumeration | whiteSpace | pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?)) : simpleContent restriction + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s3 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s4 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s5 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Annotation, s1); + machine.addTransition(startState, XsdSchemaToken::SimpleType, s2); + machine.addTransition(startState, XsdSchemaToken::MinExclusive, s3); + machine.addTransition(startState, XsdSchemaToken::MinInclusive, s3); + machine.addTransition(startState, XsdSchemaToken::MaxExclusive, s3); + machine.addTransition(startState, XsdSchemaToken::MaxInclusive, s3); + machine.addTransition(startState, XsdSchemaToken::TotalDigits, s3); + machine.addTransition(startState, XsdSchemaToken::FractionDigits, s3); + machine.addTransition(startState, XsdSchemaToken::Length, s3); + machine.addTransition(startState, XsdSchemaToken::MinLength, s3); + machine.addTransition(startState, XsdSchemaToken::MaxLength, s3); + machine.addTransition(startState, XsdSchemaToken::Enumeration, s3); + machine.addTransition(startState, XsdSchemaToken::WhiteSpace, s3); + machine.addTransition(startState, XsdSchemaToken::Pattern, s3); + machine.addTransition(startState, XsdSchemaToken::Attribute, s4); + machine.addTransition(startState, XsdSchemaToken::AttributeGroup, s4); + machine.addTransition(startState, XsdSchemaToken::AnyAttribute, s5); + + machine.addTransition(s1, XsdSchemaToken::SimpleType, s2); + machine.addTransition(s1, XsdSchemaToken::MinExclusive, s3); + machine.addTransition(s1, XsdSchemaToken::MinInclusive, s3); + machine.addTransition(s1, XsdSchemaToken::MaxExclusive, s3); + machine.addTransition(s1, XsdSchemaToken::MaxInclusive, s3); + machine.addTransition(s1, XsdSchemaToken::TotalDigits, s3); + machine.addTransition(s1, XsdSchemaToken::FractionDigits, s3); + machine.addTransition(s1, XsdSchemaToken::Length, s3); + machine.addTransition(s1, XsdSchemaToken::MinLength, s3); + machine.addTransition(s1, XsdSchemaToken::MaxLength, s3); + machine.addTransition(s1, XsdSchemaToken::Enumeration, s3); + machine.addTransition(s1, XsdSchemaToken::WhiteSpace, s3); + machine.addTransition(s1, XsdSchemaToken::Pattern, s3); + machine.addTransition(s1, XsdSchemaToken::Attribute, s4); + machine.addTransition(s1, XsdSchemaToken::AttributeGroup, s4); + machine.addTransition(s1, XsdSchemaToken::AnyAttribute, s5); + + machine.addTransition(s2, XsdSchemaToken::MinExclusive, s3); + machine.addTransition(s2, XsdSchemaToken::MinInclusive, s3); + machine.addTransition(s2, XsdSchemaToken::MaxExclusive, s3); + machine.addTransition(s2, XsdSchemaToken::MaxInclusive, s3); + machine.addTransition(s2, XsdSchemaToken::TotalDigits, s3); + machine.addTransition(s2, XsdSchemaToken::FractionDigits, s3); + machine.addTransition(s2, XsdSchemaToken::Length, s3); + machine.addTransition(s2, XsdSchemaToken::MinLength, s3); + machine.addTransition(s2, XsdSchemaToken::MaxLength, s3); + machine.addTransition(s2, XsdSchemaToken::Enumeration, s3); + machine.addTransition(s2, XsdSchemaToken::WhiteSpace, s3); + machine.addTransition(s2, XsdSchemaToken::Pattern, s3); + machine.addTransition(s2, XsdSchemaToken::Attribute, s4); + machine.addTransition(s2, XsdSchemaToken::AttributeGroup, s4); + machine.addTransition(s2, XsdSchemaToken::AnyAttribute, s5); + + machine.addTransition(s3, XsdSchemaToken::MinExclusive, s3); + machine.addTransition(s3, XsdSchemaToken::MinInclusive, s3); + machine.addTransition(s3, XsdSchemaToken::MaxExclusive, s3); + machine.addTransition(s3, XsdSchemaToken::MaxInclusive, s3); + machine.addTransition(s3, XsdSchemaToken::TotalDigits, s3); + machine.addTransition(s3, XsdSchemaToken::FractionDigits, s3); + machine.addTransition(s3, XsdSchemaToken::Length, s3); + machine.addTransition(s3, XsdSchemaToken::MinLength, s3); + machine.addTransition(s3, XsdSchemaToken::MaxLength, s3); + machine.addTransition(s3, XsdSchemaToken::Enumeration, s3); + machine.addTransition(s3, XsdSchemaToken::WhiteSpace, s3); + machine.addTransition(s3, XsdSchemaToken::Pattern, s3); + machine.addTransition(s3, XsdSchemaToken::Attribute, s4); + machine.addTransition(s3, XsdSchemaToken::AttributeGroup, s4); + machine.addTransition(s3, XsdSchemaToken::AnyAttribute, s5); + + machine.addTransition(s4, XsdSchemaToken::Attribute, s4); + machine.addTransition(s4, XsdSchemaToken::AttributeGroup, s4); + machine.addTransition(s4, XsdSchemaToken::AnyAttribute, s5); + + QVector data1, data2, data3, data4, data5, data6; + + data1 << XsdSchemaToken::Annotation; + data2 << XsdSchemaToken::SimpleType << XsdSchemaToken::MinExclusive << XsdSchemaToken::MaxExclusive; + data3 << XsdSchemaToken::AnyAttribute << XsdSchemaToken::Attribute; + data4 << XsdSchemaToken::MinExclusive << XsdSchemaToken::TotalDigits << XsdSchemaToken::Enumeration; + data5 << XsdSchemaToken::Annotation << XsdSchemaToken::Annotation; + + QVERIFY(runTest(data1, machine) == true); + QVERIFY(runTest(data2, machine) == true); + QVERIFY(runTest(data3, machine) == false); + QVERIFY(runTest(data4, machine) == true); + QVERIFY(runTest(data5, machine) == false); + QVERIFY(runTest(data6, machine) == true); +} + +void tst_XMLPatternsSchema::stateMachineTest19() +{ + XsdStateMachine machine; + + // setup state machine for (annotation?, (group | all | choice | sequence)?, ((attribute | attributeGroup)*, anyAttribute?)) : complex content restriction/complex content extension + const XsdStateMachine::StateId startState = machine.addState(XsdStateMachine::StartEndState); + const XsdStateMachine::StateId s1 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s2 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s3 = machine.addState(XsdStateMachine::EndState); + const XsdStateMachine::StateId s4 = machine.addState(XsdStateMachine::EndState); + + machine.addTransition(startState, XsdSchemaToken::Annotation, s1); + machine.addTransition(startState, XsdSchemaToken::Group, s2); + machine.addTransition(startState, XsdSchemaToken::All, s2); + machine.addTransition(startState, XsdSchemaToken::Choice, s2); + machine.addTransition(startState, XsdSchemaToken::Sequence, s2); + machine.addTransition(startState, XsdSchemaToken::Attribute, s3); + machine.addTransition(startState, XsdSchemaToken::AttributeGroup, s3); + machine.addTransition(startState, XsdSchemaToken::AnyAttribute, s4); + + machine.addTransition(s1, XsdSchemaToken::Group, s2); + machine.addTransition(s1, XsdSchemaToken::All, s2); + machine.addTransition(s1, XsdSchemaToken::Choice, s2); + machine.addTransition(s1, XsdSchemaToken::Sequence, s2); + machine.addTransition(s1, XsdSchemaToken::Attribute, s3); + machine.addTransition(s1, XsdSchemaToken::AttributeGroup, s3); + machine.addTransition(s1, XsdSchemaToken::AnyAttribute, s4); + + machine.addTransition(s2, XsdSchemaToken::Attribute, s3); + machine.addTransition(s2, XsdSchemaToken::AttributeGroup, s3); + machine.addTransition(s2, XsdSchemaToken::AnyAttribute, s4); + + machine.addTransition(s3, XsdSchemaToken::Attribute, s3); + machine.addTransition(s3, XsdSchemaToken::AttributeGroup, s3); + machine.addTransition(s3, XsdSchemaToken::AnyAttribute, s4); + + QVector data1, data2, data3, data4, data5, data6; + + data1 << XsdSchemaToken::Annotation; + data2 << XsdSchemaToken::Annotation << XsdSchemaToken::Group; + data3 << XsdSchemaToken::Annotation << XsdSchemaToken::Group << XsdSchemaToken::Sequence; + data4 << XsdSchemaToken::Attribute << XsdSchemaToken::Attribute; + data5 << XsdSchemaToken::Attribute << XsdSchemaToken::Sequence; + data6 << XsdSchemaToken::Annotation << XsdSchemaToken::Annotation; + + QVERIFY(runTest(data1, machine) == true); + QVERIFY(runTest(data2, machine) == true); + QVERIFY(runTest(data3, machine) == false); + QVERIFY(runTest(data4, machine) == true); + QVERIFY(runTest(data5, machine) == false); + QVERIFY(runTest(data6, machine) == false); +} + +QTEST_MAIN(tst_XMLPatternsSchema) +#include "tst_xmlpatternsschema.moc" diff --git a/tests/auto/xmlpatternsschema/xmlpatternsschema.pro b/tests/auto/xmlpatternsschema/xmlpatternsschema.pro new file mode 100644 index 0000000..2ba869a --- /dev/null +++ b/tests/auto/xmlpatternsschema/xmlpatternsschema.pro @@ -0,0 +1,6 @@ +load(qttest_p4) +SOURCES += tst_xmlpatternsschema.cpp \ + +include (../xmlpatterns.pri) + +INCLUDEPATH += $$QT_BUILD_TREE/include/QtXmlPatterns/private diff --git a/tests/auto/xmlpatternsschemats/.gitignore b/tests/auto/xmlpatternsschemats/.gitignore new file mode 100644 index 0000000..5fd11f8 --- /dev/null +++ b/tests/auto/xmlpatternsschemats/.gitignore @@ -0,0 +1,4 @@ +CandidateBaseline.xml +runTests +tst_xmlpatternsschemats +runTests diff --git a/tests/auto/xmlpatternsschemats/Baseline.xml b/tests/auto/xmlpatternsschemats/Baseline.xml new file mode 100644 index 0000000..9baef9c --- /dev/null +++ b/tests/auto/xmlpatternsschemats/Baseline.xml @@ -0,0 +1,2 @@ + +

Patternist is an implementation written in C++ and with the Qt/KDE libraries. It is licensed under GNU LGPL and part of KDE, the K Desktop Environment.

XQuery
\ No newline at end of file diff --git a/tests/auto/xmlpatternsschemats/TESTSUITE/.gitignore b/tests/auto/xmlpatternsschemats/TESTSUITE/.gitignore new file mode 100644 index 0000000..35cb85e --- /dev/null +++ b/tests/auto/xmlpatternsschemats/TESTSUITE/.gitignore @@ -0,0 +1,3 @@ +testSuites.xml +xmlschema2006-11-06 +xmlschema2006-11-06-new diff --git a/tests/auto/xmlpatternsschemats/TESTSUITE/unifyCatalog.xsl b/tests/auto/xmlpatternsschemats/TESTSUITE/unifyCatalog.xsl new file mode 100644 index 0000000..325f626 --- /dev/null +++ b/tests/auto/xmlpatternsschemats/TESTSUITE/unifyCatalog.xsl @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + diff --git a/tests/auto/xmlpatternsschemats/TESTSUITE/updateSuite.sh b/tests/auto/xmlpatternsschemats/TESTSUITE/updateSuite.sh new file mode 100755 index 0000000..1770f1e --- /dev/null +++ b/tests/auto/xmlpatternsschemats/TESTSUITE/updateSuite.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +# This script updates the suite from W3C's server. +# +# NOTE: the files checked out CANNOT be added to Trolltech's +# repository at the moment, due to legal complications. + +DIRECTORY_NAME="xmlschema2006-11-06" +ARCHIVE_NAME="xsts-2007-06-20.tar.gz" + +rm -Rf $DIRECTORY_NAME + +wget http://www.w3.org/XML/2004/xml-schema-test-suite/xmlschema2006-11-06/$ARCHIVE_NAME +tar -xzf $ARCHIVE_NAME +rm $ARCHIVE_NAME + +CVSROOT=:pserver:anonymous@dev.w3.org:/sources/public cvs login +CVSROOT=:pserver:anonymous@dev.w3.org:/sources/public cvs checkout -d xmlschema2006-11-06-new XML/xml-schema-test-suite/2004-01-14/xmlschema2006-11-06 + +java net.sf.saxon.Transform -xsl:unifyCatalog.xsl $DIRECTORY_NAME/suite.xml > testSuites.xml diff --git a/tests/auto/xmlpatternsschemats/tst_xmlpatternsschemats.cpp b/tests/auto/xmlpatternsschemats/tst_xmlpatternsschemats.cpp new file mode 100644 index 0000000..7a6f4c8 --- /dev/null +++ b/tests/auto/xmlpatternsschemats/tst_xmlpatternsschemats.cpp @@ -0,0 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +****************************************************************************/ + +#include + +#ifdef QTEST_XMLPATTERNS + +#include "tst_suitetest.h" + +/*! + \internal + \brief Test QXsdSchemaParser against W3C's XSD test suite. + */ +class tst_XmlPatternsSchemaTS : public tst_SuiteTest +{ + Q_OBJECT +public: + tst_XmlPatternsSchemaTS(); +protected: + virtual void catalogPath(QString &write) const; +}; + +tst_XmlPatternsSchemaTS::tst_XmlPatternsSchemaTS() + : tst_SuiteTest(tst_SuiteTest::XsdSuite) +{ +} + +void tst_XmlPatternsSchemaTS::catalogPath(QString &write) const +{ + write = QLatin1String("TESTSUITE/testSuites.xml"); +} + +QTEST_MAIN(tst_XmlPatternsSchemaTS) + +#include "tst_xmlpatternsschemats.moc" +#else +QTEST_NOOP_MAIN +#endif + +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternsschemats/xmlpatternsschemats.pro b/tests/auto/xmlpatternsschemats/xmlpatternsschemats.pro new file mode 100644 index 0000000..4978c35 --- /dev/null +++ b/tests/auto/xmlpatternsschemats/xmlpatternsschemats.pro @@ -0,0 +1,23 @@ +load(qttest_p4) +SOURCES += tst_xmlpatternsschemats.cpp \ + ../qxmlquery/TestFundament.cpp + +include (../xmlpatterns.pri) + +contains(QT_CONFIG,xmlpatterns) { +HEADERS += ../xmlpatternsxqts/test/tst_suitetest.h +SOURCES += ../xmlpatternsxqts/test/tst_suitetest.cpp +} + +PATTERNIST_SDK = QtXmlPatternsSDK +if(!debug_and_release|build_pass):CONFIG(debug, debug|release) { + win32:PATTERNIST_SDK = $${PATTERNIST_SDK}d + else: PATTERNIST_SDK = $${PATTERNIST_SDK}_debug +} +LIBS += -l$$PATTERNIST_SDK + +INCLUDEPATH += $$QT_SOURCE_TREE/tests/auto/xmlpatternsxqts/lib/ \ + $$QT_BUILD_TREE/include/QtXmlPatterns/private \ + $$QT_SOURCE_TREE/tests/auto/xmlpatternsxqts/test \ + ../xmlpatternsxqts/test \ + ../xmlpatternsxqts/lib diff --git a/tests/auto/xmlpatternsvalidator/files/instance.xml b/tests/auto/xmlpatternsvalidator/files/instance.xml new file mode 100644 index 0000000..544ff8c --- /dev/null +++ b/tests/auto/xmlpatternsvalidator/files/instance.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/tests/auto/xmlpatternsvalidator/files/invalid_schema.xsd b/tests/auto/xmlpatternsvalidator/files/invalid_schema.xsd new file mode 100644 index 0000000..99e3525 --- /dev/null +++ b/tests/auto/xmlpatternsvalidator/files/invalid_schema.xsd @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/tests/auto/xmlpatternsvalidator/files/other_valid_schema.xsd b/tests/auto/xmlpatternsvalidator/files/other_valid_schema.xsd new file mode 100644 index 0000000..850ed92 --- /dev/null +++ b/tests/auto/xmlpatternsvalidator/files/other_valid_schema.xsd @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/tests/auto/xmlpatternsvalidator/files/sa_invalid_instance.xml b/tests/auto/xmlpatternsvalidator/files/sa_invalid_instance.xml new file mode 100644 index 0000000..1804e88 --- /dev/null +++ b/tests/auto/xmlpatternsvalidator/files/sa_invalid_instance.xml @@ -0,0 +1,3 @@ + + + diff --git a/tests/auto/xmlpatternsvalidator/files/sa_valid_instance.xml b/tests/auto/xmlpatternsvalidator/files/sa_valid_instance.xml new file mode 100644 index 0000000..47c980e --- /dev/null +++ b/tests/auto/xmlpatternsvalidator/files/sa_valid_instance.xml @@ -0,0 +1,3 @@ + + + diff --git a/tests/auto/xmlpatternsvalidator/files/valid_schema.xsd b/tests/auto/xmlpatternsvalidator/files/valid_schema.xsd new file mode 100644 index 0000000..a1b765a --- /dev/null +++ b/tests/auto/xmlpatternsvalidator/files/valid_schema.xsd @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/tests/auto/xmlpatternsvalidator/tst_xmlpatternsvalidator.cpp b/tests/auto/xmlpatternsvalidator/tst_xmlpatternsvalidator.cpp new file mode 100644 index 0000000..9643e56 --- /dev/null +++ b/tests/auto/xmlpatternsvalidator/tst_xmlpatternsvalidator.cpp @@ -0,0 +1,174 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +****************************************************************************/ + +#include +#include + +#ifdef QTEST_XMLPATTERNS + +#include "../qxmlquery/TestFundament.h" +#include "../network-settings.h" + +/*! + \class tst_XmlPatterns + \internal + \since 4.6 + \brief Tests the command line interface, \c xmlpatternsvalidator, for the XML validation code. + */ +class tst_XmlPatternsValidator : public QObject + , private TestFundament +{ + Q_OBJECT + +public: + tst_XmlPatternsValidator(); + +private Q_SLOTS: + void initTestCase(); + void xsdSupport(); + void xsdSupport_data() const; + +private: + const QString m_command; + bool m_dontRun; +}; + +tst_XmlPatternsValidator::tst_XmlPatternsValidator() + : m_command(QLatin1String("xmlpatternsvalidator")) + , m_dontRun(false) +{ +} + +void tst_XmlPatternsValidator::initTestCase() +{ + QProcess process; + process.start(m_command); + + if(!process.waitForFinished()) + { + m_dontRun = true; + QEXPECT_FAIL("", "The command line tool is not in the path, most likely because Qt " + "has been partically built, such as only the sub-src rule. No tests will be run.", Abort); + QVERIFY(false); + } +} + +void tst_XmlPatternsValidator::xsdSupport() +{ + if(m_dontRun) + QSKIP("The command line utility is not in the path.", SkipAll); + +#ifdef Q_OS_WINCE + QSKIP("WinCE: This test uses unsupported WinCE functionality", SkipAll); +#endif + + QFETCH(int, expectedExitCode); + QFETCH(QStringList, arguments); + QFETCH(QString, cwd); + + QProcess process; + + if(!cwd.isEmpty()) + process.setWorkingDirectory(inputFile(cwd)); + + process.start(m_command, arguments); + + QCOMPARE(process.exitStatus(), QProcess::NormalExit); + QVERIFY(process.waitForFinished()); + + if(process.exitCode() != expectedExitCode) + QTextStream(stderr) << "foo:" << process.readAllStandardError(); + + QCOMPARE(process.exitCode(), expectedExitCode); +} + +void tst_XmlPatternsValidator::xsdSupport_data() const +{ +#ifdef Q_OS_WINCE + return; +#endif + + QTest::addColumn("expectedExitCode"); + QTest::addColumn("arguments"); + QTest::addColumn("cwd"); + + QTest::newRow("No arguments") + << 2 + << QStringList() + << QString(); + + QTest::newRow("A valid schema") + << 0 + << QStringList(QLatin1String("files/valid_schema.xsd")) + << QString(); + + QTest::newRow("An invalid schema") + << 1 + << QStringList(QLatin1String("files/invalid_schema.xsd")) + << QString(); + + QTest::newRow("An instance and valid schema") + << 0 + << (QStringList() << QLatin1String("files/instance.xml") + << QLatin1String("files/valid_schema.xsd")) + << QString(); + + QTest::newRow("An instance and invalid schema") + << 1 + << (QStringList() << QLatin1String("files/instance.xml") + << QLatin1String("files/invalid_schema.xsd")) + << QString(); + + QTest::newRow("An instance and not matching schema") + << 1 + << (QStringList() << QLatin1String("files/instance.xml") + << QLatin1String("files/other_valid_schema.xsd")) + << QString(); + + QTest::newRow("Two instance documents") + << 1 + << (QStringList() << QLatin1String("files/instance.xml") + << QLatin1String("files/instance.xml")) + << QString(); + + QTest::newRow("Three instance documents") + << 2 + << (QStringList() << QLatin1String("files/instance.xml") + << QLatin1String("files/instance.xml") + << QLatin1String("files/instance.xml")) + << QString(); + + QTest::newRow("Two schema documents") + << 1 + << (QStringList() << QLatin1String("files/valid_schema.xsd") + << QLatin1String("files/valid_schema.xsd")) + << QString(); + + QTest::newRow("A schema aware valid instance document") + << 0 + << (QStringList() << QLatin1String("files/sa_valid_instance.xml")) + << QString(); + + QTest::newRow("A schema aware invalid instance document") + << 1 + << (QStringList() << QLatin1String("files/sa_invalid_instance.xml")) + << QString(); + + QTest::newRow("A non-schema aware instance document") + << 1 + << (QStringList() << QLatin1String("files/instance.xml")) + << QString(); +} + +QTEST_MAIN(tst_XmlPatternsValidator) + +#include "tst_xmlpatternsvalidator.moc" +#else +QTEST_NOOP_MAIN +#endif + +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternsvalidator/xmlpatternsvalidator.pro b/tests/auto/xmlpatternsvalidator/xmlpatternsvalidator.pro new file mode 100644 index 0000000..7091840 --- /dev/null +++ b/tests/auto/xmlpatternsvalidator/xmlpatternsvalidator.pro @@ -0,0 +1,5 @@ +load(qttest_p4) +SOURCES += tst_xmlpatternsvalidator.cpp \ + ../qxmlquery/TestFundament.cpp + +include (../xmlpatterns.pri) diff --git a/tests/auto/xmlpatternsview/view/MainWindow.cpp b/tests/auto/xmlpatternsview/view/MainWindow.cpp index 57aaca0..b5424a3 100644 --- a/tests/auto/xmlpatternsview/view/MainWindow.cpp +++ b/tests/auto/xmlpatternsview/view/MainWindow.cpp @@ -220,7 +220,8 @@ void MainWindow::on_actionOpen_triggered() if(fileName.isNull()) return; - openCatalog(QUrl::fromLocalFile(fileName), true, false); + m_currentSuiteType = TestSuite::XQuerySuite; + openCatalog(QUrl::fromLocalFile(fileName), true, TestSuite::XQuerySuite); } void MainWindow::on_actionOpenXSLTSCatalog_triggered() @@ -234,18 +235,34 @@ void MainWindow::on_actionOpenXSLTSCatalog_triggered() if(fileName.isNull()) return; - openCatalog(QUrl::fromLocalFile(fileName), true, true); + m_currentSuiteType = TestSuite::XsltSuite; + openCatalog(QUrl::fromLocalFile(fileName), true, TestSuite::XsltSuite); +} + +void MainWindow::on_actionOpenXSDTSCatalog_triggered() +{ + const QString fileName(QFileDialog::getOpenFileName(this, + QLatin1String("Open Test Suite Catalog"), + m_previousOpenedCatalog.toLocalFile(), + QLatin1String("Test Suite Catalog file (*.xml)"))); + + /* "If the user presses Cancel, it returns a null string." */ + if(fileName.isNull()) + return; + + m_currentSuiteType = TestSuite::XsdSuite; + openCatalog(QUrl::fromLocalFile(fileName), true, TestSuite::XsdSuite); } void MainWindow::openCatalog(const QUrl &fileName, const bool reportError, - const bool isXSLT) + const TestSuite::SuiteType suiteType) { setCurrentFile(fileName); m_previousOpenedCatalog = fileName; QString errorMsg; - TestSuite *const loadedSuite = TestSuite::openCatalog(fileName, errorMsg, false, isXSLT); + TestSuite *const loadedSuite = TestSuite::openCatalog(fileName, errorMsg, false, suiteType); if(!loadedSuite) { @@ -334,12 +351,12 @@ void MainWindow::readSettings() focusURI->setText(settings.value(QLatin1String("focusURI")).toString()); isXSLT20->setChecked(settings.value(QLatin1String("isXSLT20")).toBool()); compileOnly->setChecked(settings.value(QLatin1String("compileOnly")).toBool()); + m_currentSuiteType = (TestSuite::SuiteType)settings.value(QLatin1String("PreviousSuiteType"), isXSLT20->isChecked() ? TestSuite::XsltSuite : TestSuite::XQuerySuite).toInt(); /* Open the previously opened catalog. */ if(!m_previousOpenedCatalog.isEmpty()) { - /* We don't know what kind of catalog it is, so we just take a chance. */ - openCatalog(m_previousOpenedCatalog, false, isXSLT20->isChecked()); + openCatalog(m_previousOpenedCatalog, false, m_currentSuiteType); } sourceInput->setPlainText(settings.value(QLatin1String("sourceInput")).toString()); @@ -393,6 +410,7 @@ void MainWindow::writeSettings() settings.setValue(QLatin1String("size"), size()); settings.setValue(QLatin1String("sourceInput"), sourceInput->toPlainText()); settings.setValue(QLatin1String("PreviousOpenedCatalogFile"), m_previousOpenedCatalog); + settings.setValue(QLatin1String("PreviousSuiteType"), m_currentSuiteType); settings.setValue(QLatin1String("SelectedTab"), sourceTab->currentIndex()); settings.setValue(QLatin1String("ResultViewMethod"), testResultView->resultViewSelection->currentIndex()); @@ -470,7 +488,7 @@ void MainWindow::openRecentFile() { const QAction *const action = qobject_cast(sender()); if(action) - openCatalog(action->data().toUrl(), true, false); + openCatalog(action->data().toUrl(), true, TestSuite::XQuerySuite); } void MainWindow::closeEvent(QCloseEvent *ev) diff --git a/tests/auto/xmlpatternsview/view/MainWindow.h b/tests/auto/xmlpatternsview/view/MainWindow.h index 1d14f41..778d7cd 100644 --- a/tests/auto/xmlpatternsview/view/MainWindow.h +++ b/tests/auto/xmlpatternsview/view/MainWindow.h @@ -88,6 +88,7 @@ #include "ui_ui_MainWindow.h" #include "DebugExpressionFactory.h" +#include "TestSuite.h" QT_BEGIN_HEADER @@ -142,6 +143,8 @@ namespace QPatternistSDK void on_actionOpenXSLTSCatalog_triggered(); + void on_actionOpenXSDTSCatalog_triggered(); + /** * Executes the selected test case or test group. */ @@ -153,7 +156,7 @@ namespace QPatternistSDK * an informative message box will be displayed, if any errors occurred. */ void openCatalog(const QUrl &file, const bool reportError, - const bool isXSLT); + const TestSuite::SuiteType suitType); void openRecentFile(); @@ -205,6 +208,7 @@ namespace QPatternistSDK TestCaseView * testCaseView; TestResultView * testResultView; FunctionSignaturesView * functionView; + TestSuite::SuiteType m_currentSuiteType; }; } QT_END_NAMESPACE diff --git a/tests/auto/xmlpatternsview/view/ui_MainWindow.ui b/tests/auto/xmlpatternsview/view/ui_MainWindow.ui index 5d74331..0240350 100644 --- a/tests/auto/xmlpatternsview/view/ui_MainWindow.ui +++ b/tests/auto/xmlpatternsview/view/ui_MainWindow.ui @@ -234,6 +234,7 @@ + @@ -304,6 +305,14 @@ Ctrl+L + + + O&pen XSDTS Catalog... + + + Ctrl+S + + diff --git a/tests/auto/xmlpatternsxqts/lib/TestBaseLine.cpp b/tests/auto/xmlpatternsxqts/lib/TestBaseLine.cpp index b699ead..841266c 100644 --- a/tests/auto/xmlpatternsxqts/lib/TestBaseLine.cpp +++ b/tests/auto/xmlpatternsxqts/lib/TestBaseLine.cpp @@ -178,6 +178,7 @@ void TestBaseLine::toXML(XMLWriter &receiver) const { case XML: /* Fallthrough. */ case Fragment: /* Fallthrough. */ + case SchemaIsValid: /* Fallthrough. */ case Text: { QXmlAttributes inspectAtts; @@ -343,6 +344,8 @@ TestResult::Status TestBaseLine::verify(const QString &serializedInput) const { switch(m_type) { + case SchemaIsValid: + /* Fall through. */ case Text: { if(serializedInput == details()) @@ -491,6 +494,8 @@ QString TestBaseLine::displayName(const Type id) return QLatin1String("Inspect"); case ExpectedError: return QLatin1String("ExpectedError"); + case SchemaIsValid: + return QLatin1String("SchemaIsValid"); } Q_ASSERT(false); @@ -503,6 +508,8 @@ QString TestBaseLine::details() const return QString(); if(m_type == ExpectedError) /* We're an error code. */ return m_details; + if(m_type == SchemaIsValid) /* We're a schema validation information . */ + return m_details; if(m_details.isEmpty()) return m_details; diff --git a/tests/auto/xmlpatternsxqts/lib/TestBaseLine.h b/tests/auto/xmlpatternsxqts/lib/TestBaseLine.h index 577c4b1..b5dc46e 100644 --- a/tests/auto/xmlpatternsxqts/lib/TestBaseLine.h +++ b/tests/auto/xmlpatternsxqts/lib/TestBaseLine.h @@ -168,7 +168,14 @@ namespace QPatternistSDK * because an implementation does not support the feature is not * considered a correct result. */ - ExpectedError + ExpectedError, + + /** + * A special comparison for the schema validation tests. The details + * can only be 'true' or 'false' depending on whether it is a valid + * schema or not. + */ + SchemaIsValid }; /** diff --git a/tests/auto/xmlpatternsxqts/lib/TestGroup.cpp b/tests/auto/xmlpatternsxqts/lib/TestGroup.cpp index 060f993..e59e4b4 100644 --- a/tests/auto/xmlpatternsxqts/lib/TestGroup.cpp +++ b/tests/auto/xmlpatternsxqts/lib/TestGroup.cpp @@ -94,7 +94,7 @@ TestGroup::TestGroup(TreeItem *p) : m_parent(p) QVariant TestGroup::data(const Qt::ItemDataRole role, int column) const { - if(role != Qt::DisplayRole && role != Qt::BackgroundRole) + if(role != Qt::DisplayRole && role != Qt::BackgroundRole && role != Qt::ToolTipRole) return QVariant(); /* In ResultSummary, the first is the amount of passes and the second is the total. */ @@ -154,6 +154,10 @@ QVariant TestGroup::data(const Qt::ItemDataRole role, int column) const return QVariant(); } } + case Qt::ToolTipRole: + { + return description(); + } default: { Q_ASSERT_X(false, Q_FUNC_INFO, "This shouldn't be reached"); diff --git a/tests/auto/xmlpatternsxqts/lib/TestSuite.cpp b/tests/auto/xmlpatternsxqts/lib/TestSuite.cpp index 3bca281..13d5880 100644 --- a/tests/auto/xmlpatternsxqts/lib/TestSuite.cpp +++ b/tests/auto/xmlpatternsxqts/lib/TestSuite.cpp @@ -91,6 +91,7 @@ #include "TestSuiteResult.h" #include "XMLWriter.h" #include "XSLTTestSuiteHandler.h" +#include "XSDTestSuiteHandler.h" #include "qdebug_p.h" #include "TestSuite.h" @@ -132,7 +133,7 @@ TestSuiteResult *TestSuite::runSuite() TestSuite *TestSuite::openCatalog(const QUrl &catalogURI, QString &errorMsg, const bool useExclusionList, - const bool isXSLTCatalog) + SuiteType suiteType) { pDebug() << "Opening catalog:" << catalogURI.toString(); QFile ts(catalogURI.toLocalFile()); @@ -167,14 +168,14 @@ TestSuite *TestSuite::openCatalog(const QUrl &catalogURI, return 0; } - return openCatalog(&ts, errorMsg, catalogURI, useExclusionList, isXSLTCatalog); + return openCatalog(&ts, errorMsg, catalogURI, useExclusionList, suiteType); } TestSuite *TestSuite::openCatalog(QIODevice *input, QString &errorMsg, const QUrl &fileName, const bool useExclusionList, - const bool isXSLTCatalog) + SuiteType suiteType) { Q_ASSERT(input); @@ -183,10 +184,12 @@ TestSuite *TestSuite::openCatalog(QIODevice *input, HandlerPtr loader; - if(isXSLTCatalog) - loader = HandlerPtr(new XSLTTestSuiteHandler(fileName)); - else - loader = HandlerPtr(new TestSuiteHandler(fileName, useExclusionList)); + switch (suiteType) { + case XQuerySuite: loader = HandlerPtr(new TestSuiteHandler(fileName, useExclusionList)); break; + case XsltSuite: loader = HandlerPtr(new XSLTTestSuiteHandler(fileName)); break; + case XsdSuite: loader = HandlerPtr(new XSDTestSuiteHandler(fileName)); break; + default: Q_ASSERT(false); break; + } reader.setContentHandler(loader.data()); @@ -198,8 +201,13 @@ TestSuite *TestSuite::openCatalog(QIODevice *input, return 0; } - TestSuite *const suite = isXSLTCatalog ? static_cast(loader.data())->testSuite() - : static_cast(loader.data())->testSuite(); + TestSuite *suite = 0; + switch (suiteType) { + case XQuerySuite: suite = static_cast(loader.data())->testSuite(); break; + case XsltSuite: suite = static_cast(loader.data())->testSuite(); break; + case XsdSuite: suite = static_cast(loader.data())->testSuite(); break; + default: Q_ASSERT(false); break; + } if(suite) return suite; diff --git a/tests/auto/xmlpatternsxqts/lib/TestSuite.h b/tests/auto/xmlpatternsxqts/lib/TestSuite.h index cdd511f..5141886 100644 --- a/tests/auto/xmlpatternsxqts/lib/TestSuite.h +++ b/tests/auto/xmlpatternsxqts/lib/TestSuite.h @@ -112,6 +112,16 @@ namespace QPatternistSDK class Q_PATTERNISTSDK_EXPORT TestSuite : public TestContainer { public: + /** + * Describes the type of test suite. + */ + enum SuiteType + { + XQuerySuite, ///< The test suite for XQuery + XsltSuite, ///< The test suite for XSLT + XsdSuite ///< The test suite for XML Schema + }; + TestSuite(); virtual QVariant data(const Qt::ItemDataRole role, int column) const; @@ -148,7 +158,7 @@ namespace QPatternistSDK static TestSuite *openCatalog(const QUrl &catalogFile, QString &errorMsg, const bool useExclusionList, - const bool isXSLTCatalog = false); + SuiteType type); void toXML(XMLWriter &receiver, TestCase *const tc) const; @@ -177,7 +187,7 @@ namespace QPatternistSDK QString &errorMsg, const QUrl &fileName, const bool useExclusionList, - const bool isXSLTCatalog); + SuiteType type); QString m_version; QDate m_designDate; }; diff --git a/tests/auto/xmlpatternsxqts/lib/TreeModel.cpp b/tests/auto/xmlpatternsxqts/lib/TreeModel.cpp index d9ba200..4991b26 100644 --- a/tests/auto/xmlpatternsxqts/lib/TreeModel.cpp +++ b/tests/auto/xmlpatternsxqts/lib/TreeModel.cpp @@ -118,9 +118,14 @@ QVariant TreeModel::headerData(int section, Qt::Orientation orientation, int rol return QVariant(); } -void TreeModel::childChanged(TreeItem *) +void TreeModel::childChanged(TreeItem *item) { - layoutChanged(); + if (item) { + const QModelIndex index = createIndex(item->row(), 0, item); + dataChanged(index, index); + } else { + layoutChanged(); + } } QModelIndex TreeModel::index(int row, int column, const QModelIndex &p) const diff --git a/tests/auto/xmlpatternsxqts/lib/XSDTSTestCase.cpp b/tests/auto/xmlpatternsxqts/lib/XSDTSTestCase.cpp new file mode 100644 index 0000000..b19eb91 --- /dev/null +++ b/tests/auto/xmlpatternsxqts/lib/XSDTSTestCase.cpp @@ -0,0 +1,346 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Patternist project on Trolltech Labs. +** +** $TROLLTECH_GPL_LICENSE$ +** +*************************************************************************** +*/ + +#include +#include +#include +#include +#include + +#include "XSDTSTestCase.h" + +#include "qxmlschema.h" +#include "qxmlschemavalidator.h" + +using namespace QPatternistSDK; +using namespace QPatternist; + +XSDTSTestCase::XSDTSTestCase(const Scenario scen, TreeItem *p, TestType testType) + : m_scenario(scen) + , m_parent(p) + , m_testType(testType) +{ +} + +XSDTSTestCase::~XSDTSTestCase() +{ + qDeleteAll(m_baseLines); +} + +TestResult::List XSDTSTestCase::execute(const ExecutionStage, TestSuite*) +{ + ErrorHandler errHandler; + ErrorHandler::installQtMessageHandler(&errHandler); + + TestResult::List retval; + TestResult::Status resultStatus = TestResult::Unknown; + QString serialized; + + if (m_testType == SchemaTest) { + executeSchemaTest(resultStatus, serialized, &errHandler); + } else { + executeInstanceTest(resultStatus, serialized, &errHandler); + } + + resultStatus = TestBaseLine::scan(serialized, baseLines()); + Q_ASSERT(resultStatus != TestResult::Unknown); + + m_result = new TestResult(name(), resultStatus, 0, errHandler.messages(), + QPatternist::Item::List(), serialized); + retval.append(m_result); + ErrorHandler::installQtMessageHandler(0); + changed(this); + return retval; +} + +void XSDTSTestCase::executeSchemaTest(TestResult::Status &resultStatus, QString &serialized, QAbstractMessageHandler *handler) +{ + QFile file(m_schemaUri.path()); + if (!file.open(QIODevice::ReadOnly)) { + resultStatus = TestResult::Fail; + serialized = QString(); + return; + } + + QXmlSchema schema; + schema.setMessageHandler(handler); + schema.load(&file, m_schemaUri); + + if (schema.isValid()) { + resultStatus = TestResult::Pass; + serialized = QString::fromLatin1("true"); + } else { + resultStatus = TestResult::Pass; + serialized = QString::fromLatin1("false"); + } +} + +void XSDTSTestCase::executeInstanceTest(TestResult::Status &resultStatus, QString &serialized, QAbstractMessageHandler *handler) +{ + QFile instanceFile(m_instanceUri.path()); + if (!instanceFile.open(QIODevice::ReadOnly)) { + resultStatus = TestResult::Fail; + serialized = QString(); + return; + } + + QXmlSchema schema; + if (m_schemaUri.isValid()) { + QFile file(m_schemaUri.path()); + if (!file.open(QIODevice::ReadOnly)) { + resultStatus = TestResult::Fail; + serialized = QString(); + return; + } + + schema.setMessageHandler(handler); + schema.load(&file, m_schemaUri); + + if (!schema.isValid()) { + resultStatus = TestResult::Pass; + serialized = QString::fromLatin1("false"); + return; + } + } + + QXmlSchemaValidator validator(schema); + validator.setMessageHandler(handler); + + qDebug("check %s", qPrintable(m_instanceUri.path())); + if (validator.validate(&instanceFile, m_instanceUri)) { + resultStatus = TestResult::Pass; + serialized = QString::fromLatin1("true"); + } else { + resultStatus = TestResult::Pass; + serialized = QString::fromLatin1("false"); + } +} + +QVariant XSDTSTestCase::data(const Qt::ItemDataRole role, int column) const +{ + if(role == Qt::DisplayRole) + { + if(column == 0) + return title(); + + const TestResult *const tr = testResult(); + if(!tr) + { + if(column == 1) + return TestResult::displayName(TestResult::NotTested); + else + return QString(); + } + const TestResult::Status status = tr->status(); + + switch(column) + { + case 1: + return status == TestResult::Pass ? QString(QChar::fromLatin1('1')) + : QString(QChar::fromLatin1('0')); + case 2: + return status == TestResult::Fail ? QString(QChar::fromLatin1('1')) + : QString(QChar::fromLatin1('0')); + default: + return QString(); + } + } + + if(role != Qt::BackgroundRole) + return QVariant(); + + const TestResult *const tr = testResult(); + + if(!tr) + { + if(column == 0) + return Qt::yellow; + else + return QVariant(); + } + + const TestResult::Status status = tr->status(); + + if(status == TestResult::NotTested || status == TestResult::Unknown) + return Qt::yellow; + + switch(column) + { + case 1: + return status == TestResult::Pass ? Qt::green : QVariant(); + case 2: + return status == TestResult::Fail ? Qt::red : QVariant(); + default: + return QVariant(); + } +} + +QString XSDTSTestCase::sourceCode(bool &ok) const +{ + QFile file((m_testType == SchemaTest ? m_schemaUri : m_instanceUri).toLocalFile()); + + QString err; + + if(!file.exists()) + err = QString::fromLatin1("Error: %1 does not exist.").arg(file.fileName()); + else if(!QFileInfo(file.fileName()).isFile()) + err = QString::fromLatin1("Error: %1 is not a file, cannot display it.").arg(file.fileName()); + else if(!file.open(QIODevice::ReadOnly)) + err = QString::fromLatin1("Error: Could not open %1. Likely a permission error.") + .arg(file.fileName()); + + if(err.isNull()) /* No errors. */ + { + ok = true; + /* Scary, we assume the query is stored in UTF-8. */ + return QString::fromUtf8(file.readAll()); + } + else + { + ok = false; + return err; + } +} + +int XSDTSTestCase::columnCount() const +{ + return 2; +} + +void XSDTSTestCase::addBaseLine(TestBaseLine *line) +{ + m_baseLines.append(line); +} + +QString XSDTSTestCase::name() const +{ + return m_name; +} + +QString XSDTSTestCase::creator() const +{ + return m_creator; +} + +QString XSDTSTestCase::description() const +{ + return m_description; +} + +QDate XSDTSTestCase::lastModified() const +{ + return m_lastModified; +} + +bool XSDTSTestCase::isXPath() const +{ + return false; +} + +TestCase::Scenario XSDTSTestCase::scenario() const +{ + return m_scenario; +} + +void XSDTSTestCase::setName(const QString &n) +{ + m_name = n; +} + +void XSDTSTestCase::setCreator(const QString &ctor) +{ + m_creator = ctor; +} + +void XSDTSTestCase::setDescription(const QString &descriptionP) +{ + m_description = descriptionP; +} + +void XSDTSTestCase::setLastModified(const QDate &date) +{ + m_lastModified = date; +} + +void XSDTSTestCase::setSchemaUri(const QUrl &uri) +{ + m_schemaUri = uri; +} + +void XSDTSTestCase::setInstanceUri(const QUrl &uri) +{ + m_instanceUri = uri; +} + +TreeItem *XSDTSTestCase::parent() const +{ + return m_parent; +} + +QString XSDTSTestCase::title() const +{ + return m_name; +} + +TestBaseLine::List XSDTSTestCase::baseLines() const +{ + Q_ASSERT_X(!m_baseLines.isEmpty(), Q_FUNC_INFO, + qPrintable(QString::fromLatin1("The test %1 has no base lines, it should have at least one.").arg(name()))); + return m_baseLines; +} + +QUrl XSDTSTestCase::schemaUri() const +{ + return m_schemaUri; +} + +QUrl XSDTSTestCase::instanceUri() const +{ + return m_instanceUri; +} + +void XSDTSTestCase::setContextItemSource(const QUrl &uri) +{ + m_contextItemSource = uri; +} + +QUrl XSDTSTestCase::contextItemSource() const +{ + return m_contextItemSource; +} + +void XSDTSTestCase::setParent(TreeItem *const p) +{ + m_parent = p; +} + +QPatternist::ExternalVariableLoader::Ptr XSDTSTestCase::externalVariableLoader() const +{ + return QPatternist::ExternalVariableLoader::Ptr(); +} + +TestResult *XSDTSTestCase::testResult() const +{ + return m_result; +} + +TestItem::ResultSummary XSDTSTestCase::resultSummary() const +{ + if(m_result) + return ResultSummary(m_result->status() == TestResult::Pass ? 1 : 0, + 1); + + return ResultSummary(0, 1); +} + +// vim: et:ts=4:sw=4:sts=4 + diff --git a/tests/auto/xmlpatternsxqts/lib/XSDTSTestCase.h b/tests/auto/xmlpatternsxqts/lib/XSDTSTestCase.h new file mode 100644 index 0000000..ce84988 --- /dev/null +++ b/tests/auto/xmlpatternsxqts/lib/XSDTSTestCase.h @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Patternist project on Trolltech Labs. +** +** $TROLLTECH_GPL_LICENSE$ +** +*************************************************************************** +*/ + +#ifndef PatternistSDK_XSDTSTestCase_H +#define PatternistSDK_XSDTSTestCase_H + +#include +#include +#include + +#include "TestBaseLine.h" +#include "TestCase.h" + +QT_BEGIN_HEADER + +namespace QPatternistSDK +{ + /** + * @short Represents a test case in a test suite in the XML Query Test Suite. + * + * TestCase is a memory representation of a test case, and maps + * to the @c test-case element in the XQuery Test Suite test + * case catalog. + * + * @ingroup PatternistSDK + * @author Frans Englich + */ + class Q_PATTERNISTSDK_EXPORT XSDTSTestCase : public TestCase + { + public: + enum TestType + { + SchemaTest, + InstanceTest + }; + + XSDTSTestCase(const Scenario scen, TreeItem *parent, TestType testType); + virtual ~XSDTSTestCase(); + + /** + * Executes the test, and returns the result. The returned list + * will always contain exactly one TestResult. + * + * @p stage is ignored when running out-of-process. + */ + virtual TestResult::List execute(const ExecutionStage stage, + TestSuite *ts); + /** + * The identifier, the name of the test. For example, "Literals034". + * The name of a test case must be unique. + */ + virtual QString name() const; + virtual QString creator() const; + virtual QString description() const; + /** + * @returns the query inside the file, specified by testCasePath(). Loading + * of the file is not cached in order to avoid complications. + * @param ok is set to @c false if loading the query file fails + */ + virtual QString sourceCode(bool &ok) const; + virtual QUrl schemaUri() const; + virtual QUrl instanceUri() const; + virtual QUrl testCasePath() const {return QUrl();} + virtual QDate lastModified() const; + + bool isXPath() const; + + /** + * What kind of test case this is, what kind of scenario it takes part + * of. For example, whether the test case should evaluate normally or fail. + */ + Scenario scenario() const; + + void setCreator(const QString &creator); + void setLastModified(const QDate &date); + void setDescription(const QString &description); + void setName(const QString &name); + void setSchemaUri(const QUrl &uri); + void setInstanceUri(const QUrl &uri); + void setTestCasePath(const QUrl &uri) {} + void setContextItemSource(const QUrl &uri); + void addBaseLine(TestBaseLine *lines); + + virtual TreeItem *parent() const; + + virtual QVariant data(const Qt::ItemDataRole role, int column) const; + + virtual QString title() const; + virtual TestBaseLine::List baseLines() const; + + virtual int columnCount() const; + + virtual QUrl contextItemSource() const; + void setParent(TreeItem *const parent); + virtual QPatternist::ExternalVariableLoader::Ptr externalVariableLoader() const; + virtual TestResult *testResult() const; + virtual ResultSummary resultSummary() const; + + private: + void executeSchemaTest(TestResult::Status &resultStatus, QString &serialized, QAbstractMessageHandler *handler); + void executeInstanceTest(TestResult::Status &resultStatus, QString &serialized, QAbstractMessageHandler *handler); + + QString m_name; + QString m_creator; + QString m_description; + QUrl m_schemaUri; + QUrl m_instanceUri; + QDate m_lastModified; + const Scenario m_scenario; + TreeItem * m_parent; + TestBaseLine::List m_baseLines; + QUrl m_contextItemSource; + TestType m_testType; + QPointer m_result; + }; +} + +QT_END_HEADER + +#endif +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternsxqts/lib/XSDTestSuiteHandler.cpp b/tests/auto/xmlpatternsxqts/lib/XSDTestSuiteHandler.cpp new file mode 100644 index 0000000..b6ee379 --- /dev/null +++ b/tests/auto/xmlpatternsxqts/lib/XSDTestSuiteHandler.cpp @@ -0,0 +1,881 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Patternist project on Trolltech Labs. +** +** $TROLLTECH_GPL_LICENSE$ +** +*************************************************************************** +*/ + +#include + +#include "qacceltreeresourceloader_p.h" +#include "qnetworkaccessdelegator_p.h" + +#include "Global.h" +#include "TestBaseLine.h" +#include "TestGroup.h" + +#include "XSDTestSuiteHandler.h" +#include "XSDTSTestCase.h" + +using namespace QPatternistSDK; + +extern QNetworkAccessManager s_networkManager; + +XSDTestSuiteHandler::XSDTestSuiteHandler(const QUrl &catalogFile) : m_ts(0) + , m_catalogFile(catalogFile) + , m_inSchemaTest(false) + , m_inInstanceTest(false) + , m_inTestGroup(false) + , m_inDescription(false) + , m_schemaBlacklisted(false) + , m_counter(0) +{ + Q_ASSERT(!m_catalogFile.isRelative()); + m_ts = new TestSuite(); + m_topLevelGroup = new TestGroup(m_ts); + m_topLevelGroup->setTitle("XML Schema Test Suite"); + m_ts->appendChild(m_topLevelGroup); + + // exclude these test cases, as they break our current state machine + m_blackList << QLatin1String("addB099") + << QLatin1String("addB118") + << QLatin1String("elemJ003") + << QLatin1String("elemJ011") + << QLatin1String("elemZ004") + << QLatin1String("elemZ020") + << QLatin1String("groupH021v") + << QLatin1String("groupJ009v") + << QLatin1String("name00101m2") + << QLatin1String("schL5") + << QLatin1String("ste110") + << QLatin1String("stZ007") + << QLatin1String("stZ047") + << QLatin1String("stZ055") + << QLatin1String("addB049") + << QLatin1String("addB068") + << QLatin1String("addB078") + << QLatin1String("addB078A") + << QLatin1String("addB078B") + << QLatin1String("addB167") + << QLatin1String("addB191") + << QLatin1String("isDefault060_2") + << QLatin1String("isDefault069") + << QLatin1String("annotB025") + << QLatin1String("base64Binary_enumeration003_1321") + << QLatin1String("anyURI_a001_1336") + << QLatin1String("anyURI_a001_1336") + << QLatin1String("anyURI_a003_1338") + << QLatin1String("anyURI_a004_1339") + << QLatin1String("anyURI_b004_1354") + << QLatin1String("anyURI_b004_1354") + << QLatin1String("anyURI_b006_1356") + << QLatin1String("QName_length001_1357") + << QLatin1String("QName_length003_1359") + << QLatin1String("QName_minLength003_1362") + << QLatin1String("QName_maxLength001_1364") + << QLatin1String("NOTATION_length001_1372") + << QLatin1String("NOTATION_length003_1374") + << QLatin1String("NOTATION_minLength003_1377") + << QLatin1String("NOTATION_maxLength001_1379") + << QLatin1String("hexBinary003_2069") + << QLatin1String("QName009_2092") + << QLatin1String("dtZ107447_a_2245") + << QLatin1String("elemE001") + << QLatin1String("elemE002") + << QLatin1String("elemE003") + << QLatin1String("elemE004") + << QLatin1String("elemE005") + << QLatin1String("elemT026") + << QLatin1String("elemT027") + << QLatin1String("elemT028") + << QLatin1String("elemT029") + << QLatin1String("elemT054") + << QLatin1String("elemT055") + << QLatin1String("elemT056") + << QLatin1String("elemT057") + << QLatin1String("elemZ006") + << QLatin1String("elemZ007") + << QLatin1String("elemZ026") + << QLatin1String("elemZ027_c") + << QLatin1String("elemZ028c") + << QLatin1String("elemZ028d") + << QLatin1String("elemZ028f1") + << QLatin1String("elemZ028f1") + << QLatin1String("elemZ028f2") + << QLatin1String("elemZ028f2") + << QLatin1String("elemZ028f3") + << QLatin1String("elemZ028f3") + << QLatin1String("elemZ031") + << QLatin1String("errF001") + << QLatin1String("idC019") + << QLatin1String("idL100") + << QLatin1String("idZ011") + << QLatin1String("idZ015") + << QLatin1String("mgO013") + << QLatin1String("particlesA012") + << QLatin1String("particlesA013") + << QLatin1String("particlesA014") + << QLatin1String("particlesA015") + << QLatin1String("particlesHa161") + << QLatin1String("particlesHb008") + << QLatin1String("particlesHb011") + << QLatin1String("particlesIe003") + << QLatin1String("particlesIg003") + << QLatin1String("particlesIg004") + << QLatin1String("particlesJb003") + << QLatin1String("particlesJd003") + << QLatin1String("particlesJf003") + << QLatin1String("particlesJk003") + << QLatin1String("particlesOb001") + << QLatin1String("particlesOb002") + << QLatin1String("particlesOb004") + << QLatin1String("particlesOb008") + << QLatin1String("particlesOb009") + << QLatin1String("particlesOb013") + << QLatin1String("particlesOb018") + << QLatin1String("particlesQ005") + << QLatin1String("particlesS002") + << QLatin1String("particlesT002") + << QLatin1String("particlesT009") + << QLatin1String("particlesT014") + << QLatin1String("particlesV001") + << QLatin1String("particlesV002") + << QLatin1String("particlesV020") + << QLatin1String("particlesZ001") + << QLatin1String("particlesZ005") + << QLatin1String("particlesZ007") + << QLatin1String("particlesZ023") + << QLatin1String("particlesZ024") + << QLatin1String("particlesZ026") + << QLatin1String("particlesZ028") + << QLatin1String("particlesZ033_c") + << QLatin1String("particlesZ033_d") + << QLatin1String("particlesZ033_e") + << QLatin1String("particlesZ033_f") + << QLatin1String("particlesZ033_g") + << QLatin1String("particlesZ034_a1") + << QLatin1String("particlesZ034_a2") + << QLatin1String("particlesZ034_a3") + << QLatin1String("particlesZ034_b") + << QLatin1String("particlesZ035_a") + << QLatin1String("particlesZ035_b") + << QLatin1String("particlesZ036_a") + << QLatin1String("particlesZ036_b1") + << QLatin1String("particlesZ036_b2") + << QLatin1String("particlesZ036_c") +/* + << QLatin1String("reC65") + << QLatin1String("reC66") + << QLatin1String("reC67") + << QLatin1String("reC68") + << QLatin1String("reF58") + << QLatin1String("reG50") + << QLatin1String("reJ11") + << QLatin1String("reJ13") + << QLatin1String("reJ19") + << QLatin1String("reJ21") + << QLatin1String("reJ23") + << QLatin1String("reJ25") + << QLatin1String("reJ29") + << QLatin1String("reJ31") + << QLatin1String("reJ33") + << QLatin1String("reJ35") + << QLatin1String("reJ61") + << QLatin1String("reJ69") + << QLatin1String("reJ75") + << QLatin1String("reJ77") + << QLatin1String("reL98") + << QLatin1String("reL99") + << QLatin1String("reM98") + << QLatin1String("reN99") + << QLatin1String("reS21") + << QLatin1String("reS42") + << QLatin1String("reT63") + << QLatin1String("reT84") + << QLatin1String("reDG2") + << QLatin1String("RegexTest_9") + << QLatin1String("RegexTest_11") + << QLatin1String("RegexTest_14") + << QLatin1String("RegexTest_15") + << QLatin1String("RegexTest_16") + << QLatin1String("RegexTest_17") + << QLatin1String("RegexTest_23") + << QLatin1String("RegexTest_24") + << QLatin1String("RegexTest_25") + << QLatin1String("RegexTest_26") + << QLatin1String("RegexTest_27") + << QLatin1String("RegexTest_28") + << QLatin1String("RegexTest_30") + << QLatin1String("RegexTest_30") + << QLatin1String("RegexTest_33") + << QLatin1String("RegexTest_34") + << QLatin1String("RegexTest_34") + << QLatin1String("RegexTest_43") + << QLatin1String("RegexTest_44") + << QLatin1String("RegexTest_45") + << QLatin1String("RegexTest_46") + << QLatin1String("RegexTest_47") + << QLatin1String("RegexTest_48") + << QLatin1String("RegexTest_49") + << QLatin1String("RegexTest_50") + << QLatin1String("RegexTest_51") + << QLatin1String("RegexTest_52") + << QLatin1String("RegexTest_53") + << QLatin1String("RegexTest_54") + << QLatin1String("RegexTest_55") + << QLatin1String("RegexTest_56") + << QLatin1String("RegexTest_57") + << QLatin1String("RegexTest_57") + << QLatin1String("RegexTest_58") + << QLatin1String("RegexTest_58") + << QLatin1String("RegexTest_65") + << QLatin1String("RegexTest_113") + << QLatin1String("RegexTest_116") + << QLatin1String("RegexTest_119") + << QLatin1String("RegexTest_120") + << QLatin1String("RegexTest_121") + << QLatin1String("RegexTest_141") + << QLatin1String("RegexTest_142") + << QLatin1String("RegexTest_143") + << QLatin1String("RegexTest_145") + << QLatin1String("RegexTest_146") + << QLatin1String("RegexTest_147") + << QLatin1String("RegexTest_148") + << QLatin1String("RegexTest_149") + << QLatin1String("RegexTest_150") + << QLatin1String("RegexTest_151") + << QLatin1String("RegexTest_152") + << QLatin1String("RegexTest_154") + << QLatin1String("RegexTest_155") + << QLatin1String("RegexTest_156") + << QLatin1String("RegexTest_157") + << QLatin1String("RegexTest_158") + << QLatin1String("RegexTest_163") + << QLatin1String("RegexTest_164") + << QLatin1String("RegexTest_165") + << QLatin1String("RegexTest_166") + << QLatin1String("RegexTest_167") + << QLatin1String("RegexTest_168") + << QLatin1String("RegexTest_169") + << QLatin1String("RegexTest_170") + << QLatin1String("RegexTest_171") + << QLatin1String("RegexTest_172") + << QLatin1String("RegexTest_173") + << QLatin1String("RegexTest_174") + << QLatin1String("RegexTest_178") + << QLatin1String("RegexTest_194") + << QLatin1String("RegexTest_194") + << QLatin1String("RegexTest_195") + << QLatin1String("RegexTest_195") + << QLatin1String("RegexTest_196") + << QLatin1String("RegexTest_196") + << QLatin1String("RegexTest_197") + << QLatin1String("RegexTest_198") + << QLatin1String("RegexTest_199") + << QLatin1String("RegexTest_200") + << QLatin1String("RegexTest_200") + << QLatin1String("RegexTest_201") + << QLatin1String("RegexTest_201") + << QLatin1String("RegexTest_202") + << QLatin1String("RegexTest_202") + << QLatin1String("RegexTest_203") + << QLatin1String("RegexTest_204") + << QLatin1String("RegexTest_205") + << QLatin1String("RegexTest_206") + << QLatin1String("RegexTest_207") + << QLatin1String("RegexTest_208") + << QLatin1String("RegexTest_209") + << QLatin1String("RegexTest_209") + << QLatin1String("RegexTest_210") + << QLatin1String("RegexTest_210") + << QLatin1String("RegexTest_211") + << QLatin1String("RegexTest_211") + << QLatin1String("RegexTest_212") + << QLatin1String("RegexTest_213") + << QLatin1String("RegexTest_214") + << QLatin1String("RegexTest_215") + << QLatin1String("RegexTest_216") + << QLatin1String("RegexTest_217") + << QLatin1String("RegexTest_218") + << QLatin1String("RegexTest_220") + << QLatin1String("RegexTest_221") + << QLatin1String("RegexTest_222") + << QLatin1String("RegexTest_226") + << QLatin1String("RegexTest_230") + << QLatin1String("RegexTest_232") + << QLatin1String("RegexTest_233") + << QLatin1String("RegexTest_294") + << QLatin1String("RegexTest_294") + << QLatin1String("RegexTest_295") + << QLatin1String("RegexTest_295") + << QLatin1String("RegexTest_299") + << QLatin1String("RegexTest_300") + << QLatin1String("RegexTest_301") + << QLatin1String("RegexTest_302") + << QLatin1String("RegexTest_303") + << QLatin1String("RegexTest_304") + << QLatin1String("RegexTest_305") + << QLatin1String("RegexTest_306") + << QLatin1String("RegexTest_307") + << QLatin1String("RegexTest_308") + << QLatin1String("RegexTest_309") + << QLatin1String("RegexTest_310") + << QLatin1String("RegexTest_311") + << QLatin1String("RegexTest_312") + << QLatin1String("RegexTest_313") + << QLatin1String("RegexTest_314") + << QLatin1String("RegexTest_315") + << QLatin1String("RegexTest_315") + << QLatin1String("RegexTest_316") + << QLatin1String("RegexTest_316") + << QLatin1String("RegexTest_317") + << QLatin1String("RegexTest_317") + << QLatin1String("RegexTest_440") + << QLatin1String("RegexTest_441") + << QLatin1String("RegexTest_442") + << QLatin1String("RegexTest_443") + << QLatin1String("RegexTest_448") + << QLatin1String("RegexTest_449") + << QLatin1String("RegexTest_450") + << QLatin1String("RegexTest_451") + << QLatin1String("RegexTest_458") + << QLatin1String("RegexTest_464") + << QLatin1String("RegexTest_464") + << QLatin1String("RegexTest_465") + << QLatin1String("RegexTest_469") + << QLatin1String("RegexTest_470") + << QLatin1String("RegexTest_471") + << QLatin1String("RegexTest_472") + << QLatin1String("RegexTest_473") + << QLatin1String("RegexTest_477") + << QLatin1String("RegexTest_478") + << QLatin1String("RegexTest_478") + << QLatin1String("RegexTest_479") + << QLatin1String("RegexTest_480") + << QLatin1String("RegexTest_481") + << QLatin1String("RegexTest_482") + << QLatin1String("RegexTest_482") + << QLatin1String("RegexTest_483") + << QLatin1String("RegexTest_483") + << QLatin1String("RegexTest_484") + << QLatin1String("RegexTest_487") + << QLatin1String("RegexTest_516") + << QLatin1String("RegexTest_516") + << QLatin1String("RegexTest_517") + << QLatin1String("RegexTest_517") + << QLatin1String("RegexTest_518") + << QLatin1String("RegexTest_518") + << QLatin1String("RegexTest_519") + << QLatin1String("RegexTest_519") + << QLatin1String("RegexTest_521") + << QLatin1String("RegexTest_523") + << QLatin1String("RegexTest_524") + << QLatin1String("RegexTest_524") + << QLatin1String("RegexTest_586") + << QLatin1String("RegexTest_587") + << QLatin1String("RegexTest_592") + << QLatin1String("RegexTest_593") + << QLatin1String("RegexTest_594") + << QLatin1String("RegexTest_595") + << QLatin1String("RegexTest_596") + << QLatin1String("RegexTest_597") + << QLatin1String("RegexTest_598") + << QLatin1String("RegexTest_599") + << QLatin1String("RegexTest_600") + << QLatin1String("RegexTest_601") + << QLatin1String("RegexTest_602") + << QLatin1String("RegexTest_603") + << QLatin1String("RegexTest_604") + << QLatin1String("RegexTest_605") + << QLatin1String("RegexTest_648") + << QLatin1String("RegexTest_655") + << QLatin1String("RegexTest_688") + << QLatin1String("RegexTest_696") + << QLatin1String("RegexTest_697") + << QLatin1String("RegexTest_698") + << QLatin1String("RegexTest_700") + << QLatin1String("RegexTest_701") + << QLatin1String("RegexTest_702") + << QLatin1String("RegexTest_703") + << QLatin1String("RegexTest_704") + << QLatin1String("RegexTest_705") + << QLatin1String("RegexTest_706") + << QLatin1String("RegexTest_707") + << QLatin1String("RegexTest_717") + << QLatin1String("RegexTest_718") + << QLatin1String("RegexTest_719") + << QLatin1String("RegexTest_724") + << QLatin1String("RegexTest_725") + << QLatin1String("RegexTest_726") + << QLatin1String("RegexTest_727") + << QLatin1String("RegexTest_728") + << QLatin1String("RegexTest_729") + << QLatin1String("RegexTest_730") + << QLatin1String("RegexTest_731") + << QLatin1String("RegexTest_732") + << QLatin1String("RegexTest_733") + << QLatin1String("RegexTest_743") + << QLatin1String("RegexTest_755") + << QLatin1String("RegexTest_756") + << QLatin1String("RegexTest_761") + << QLatin1String("RegexTest_762") + << QLatin1String("RegexTest_781") + << QLatin1String("RegexTest_782") + << QLatin1String("RegexTest_783") + << QLatin1String("RegexTest_790") + << QLatin1String("RegexTest_791") + << QLatin1String("RegexTest_824") + << QLatin1String("RegexTest_826") + << QLatin1String("RegexTest_827") + << QLatin1String("RegexTest_836") + << QLatin1String("RegexTest_837") + << QLatin1String("RegexTest_841") + << QLatin1String("RegexTest_842") + << QLatin1String("RegexTest_843") + << QLatin1String("RegexTest_844") + << QLatin1String("RegexTest_845") + << QLatin1String("RegexTest_846") + << QLatin1String("RegexTest_847") + << QLatin1String("RegexTest_848") + << QLatin1String("RegexTest_851") + << QLatin1String("RegexTest_852") + << QLatin1String("RegexTest_853") + << QLatin1String("RegexTest_854") + << QLatin1String("RegexTest_855") + << QLatin1String("RegexTest_856") + << QLatin1String("RegexTest_857") + << QLatin1String("RegexTest_861") + << QLatin1String("RegexTest_862") + << QLatin1String("RegexTest_863") + << QLatin1String("RegexTest_864") + << QLatin1String("RegexTest_865") + << QLatin1String("RegexTest_866") + << QLatin1String("RegexTest_870") + << QLatin1String("RegexTest_879") + << QLatin1String("RegexTest_880") + << QLatin1String("RegexTest_888") + << QLatin1String("RegexTest_889") + << QLatin1String("RegexTest_890") + << QLatin1String("RegexTest_891") + << QLatin1String("RegexTest_892") + << QLatin1String("RegexTest_893") + << QLatin1String("RegexTest_894") + << QLatin1String("RegexTest_895") + << QLatin1String("RegexTest_896") + << QLatin1String("RegexTest_897") + << QLatin1String("RegexTest_898") + << QLatin1String("RegexTest_899") + << QLatin1String("RegexTest_900") + << QLatin1String("RegexTest_901") + << QLatin1String("RegexTest_902") + << QLatin1String("RegexTest_903") + << QLatin1String("RegexTest_904") + << QLatin1String("RegexTest_905") + << QLatin1String("RegexTest_906") + << QLatin1String("RegexTest_907") + << QLatin1String("RegexTest_908") + << QLatin1String("RegexTest_909") + << QLatin1String("RegexTest_910") + << QLatin1String("RegexTest_911") + << QLatin1String("RegexTest_912") + << QLatin1String("RegexTest_913") + << QLatin1String("RegexTest_914") + << QLatin1String("RegexTest_915") + << QLatin1String("RegexTest_916") + << QLatin1String("RegexTest_917") + << QLatin1String("RegexTest_918") + << QLatin1String("RegexTest_919") + << QLatin1String("RegexTest_920") + << QLatin1String("RegexTest_921") + << QLatin1String("RegexTest_922") + << QLatin1String("RegexTest_923") + << QLatin1String("RegexTest_924") + << QLatin1String("RegexTest_925") + << QLatin1String("RegexTest_926") + << QLatin1String("RegexTest_928") + << QLatin1String("RegexTest_929") + << QLatin1String("RegexTest_930") + << QLatin1String("RegexTest_936") + << QLatin1String("RegexTest_937") + << QLatin1String("RegexTest_938") + << QLatin1String("RegexTest_939") + << QLatin1String("RegexTest_940") + << QLatin1String("RegexTest_941") + << QLatin1String("RegexTest_942") + << QLatin1String("RegexTest_943") + << QLatin1String("RegexTest_944") + << QLatin1String("RegexTest_945") + << QLatin1String("RegexTest_946") + << QLatin1String("RegexTest_949") + << QLatin1String("RegexTest_950") + << QLatin1String("RegexTest_951") + << QLatin1String("RegexTest_952") + << QLatin1String("RegexTest_953") + << QLatin1String("RegexTest_954") + << QLatin1String("RegexTest_955") + << QLatin1String("RegexTest_956") + << QLatin1String("RegexTest_957") + << QLatin1String("RegexTest_958") + << QLatin1String("RegexTest_959") + << QLatin1String("RegexTest_960") + << QLatin1String("RegexTest_961") + << QLatin1String("RegexTest_962") + << QLatin1String("RegexTest_963") + << QLatin1String("RegexTest_964") + << QLatin1String("RegexTest_976") + << QLatin1String("RegexTest_977") + << QLatin1String("RegexTest_988") + << QLatin1String("RegexTest_989") + << QLatin1String("RegexTest_990") + << QLatin1String("RegexTest_991") + << QLatin1String("RegexTest_994") + << QLatin1String("RegexTest_995") + << QLatin1String("RegexTest_996") + << QLatin1String("RegexTest_997") + << QLatin1String("RegexTest_1000") + << QLatin1String("RegexTest_1001") + << QLatin1String("RegexTest_1002") + << QLatin1String("RegexTest_1003") + << QLatin1String("RegexTest_1004") + << QLatin1String("RegexTest_1007") + << QLatin1String("RegexTest_1008") + << QLatin1String("RegexTest_1009") + << QLatin1String("RegexTest_1010") + << QLatin1String("RegexTest_1011") + << QLatin1String("RegexTest_1012") + << QLatin1String("RegexTest_1013") + << QLatin1String("RegexTest_1014") + << QLatin1String("RegexTest_1015") + << QLatin1String("RegexTest_1016") + << QLatin1String("RegexTest_1017") + << QLatin1String("RegexTest_1018") + << QLatin1String("RegexTest_1019") + << QLatin1String("RegexTest_1070") + << QLatin1String("RegexTest_1071") + << QLatin1String("RegexTest_1076") + << QLatin1String("RegexTest_1077") + << QLatin1String("RegexTest_1078") + << QLatin1String("RegexTest_1079") + << QLatin1String("RegexTest_1080") + << QLatin1String("RegexTest_1081") + << QLatin1String("RegexTest_1082") + << QLatin1String("RegexTest_1083") + << QLatin1String("RegexTest_1084") + << QLatin1String("RegexTest_1085") + << QLatin1String("RegexTest_1086") + << QLatin1String("RegexTest_1087") + << QLatin1String("RegexTest_1088") + << QLatin1String("RegexTest_1089") + << QLatin1String("RegexTest_1132") + << QLatin1String("RegexTest_1139") + << QLatin1String("RegexTest_1172") + << QLatin1String("RegexTest_1180") + << QLatin1String("RegexTest_1181") + << QLatin1String("RegexTest_1182") + << QLatin1String("RegexTest_1184") + << QLatin1String("RegexTest_1185") + << QLatin1String("RegexTest_1186") + << QLatin1String("RegexTest_1187") + << QLatin1String("RegexTest_1188") + << QLatin1String("RegexTest_1189") + << QLatin1String("RegexTest_1190") + << QLatin1String("RegexTest_1191") + << QLatin1String("RegexTest_1201") + << QLatin1String("RegexTest_1202") + << QLatin1String("RegexTest_1203") + << QLatin1String("RegexTest_1208") + << QLatin1String("RegexTest_1209") + << QLatin1String("RegexTest_1210") + << QLatin1String("RegexTest_1211") + << QLatin1String("RegexTest_1212") + << QLatin1String("RegexTest_1213") + << QLatin1String("RegexTest_1214") + << QLatin1String("RegexTest_1215") + << QLatin1String("RegexTest_1216") + << QLatin1String("RegexTest_1217") + << QLatin1String("RegexTest_1227") + << QLatin1String("RegexTest_1239") + << QLatin1String("RegexTest_1240") + << QLatin1String("RegexTest_1245") + << QLatin1String("RegexTest_1246") + << QLatin1String("RegexTest_1265") + << QLatin1String("RegexTest_1266") + << QLatin1String("RegexTest_1267") + << QLatin1String("RegexTest_1274") + << QLatin1String("RegexTest_1275") + << QLatin1String("RegexTest_1308") + << QLatin1String("RegexTest_1310") + << QLatin1String("RegexTest_1311") + << QLatin1String("RegexTest_1320") + << QLatin1String("RegexTest_1321") + << QLatin1String("RegexTest_1322") + << QLatin1String("RegexTest_1323") + << QLatin1String("RegexTest_1324") + << QLatin1String("RegexTest_1325") + << QLatin1String("RegexTest_1326") + << QLatin1String("RegexTest_1327") + << QLatin1String("RegexTest_1328") + << QLatin1String("RegexTest_1329") + << QLatin1String("RegexTest_1330") + << QLatin1String("RegexTest_1331") + << QLatin1String("RegexTest_1332") + << QLatin1String("RegexTest_1335") + << QLatin1String("RegexTest_1336") + << QLatin1String("RegexTest_1337") + << QLatin1String("RegexTest_1338") + << QLatin1String("RegexTest_1339") + << QLatin1String("RegexTest_1340") + << QLatin1String("RegexTest_1341") + << QLatin1String("RegexTest_1345") + << QLatin1String("RegexTest_1346") + << QLatin1String("RegexTest_1347") + << QLatin1String("RegexTest_1348") + << QLatin1String("RegexTest_1349") + << QLatin1String("RegexTest_1350") + << QLatin1String("RegexTest_1354") + << QLatin1String("RegexTest_1363") + << QLatin1String("RegexTest_1364") + << QLatin1String("RegexTest_1365") + << QLatin1String("RegexTest_1372") + << QLatin1String("RegexTest_1373") + << QLatin1String("RegexTest_1374") + << QLatin1String("RegexTest_1375") + << QLatin1String("RegexTest_1376") + << QLatin1String("RegexTest_1377") + << QLatin1String("RegexTest_1378") + << QLatin1String("RegexTest_1379") + << QLatin1String("RegexTest_1380") + << QLatin1String("RegexTest_1381") + << QLatin1String("RegexTest_1382") + << QLatin1String("RegexTest_1383") + << QLatin1String("RegexTest_1384") + << QLatin1String("RegexTest_1385") + << QLatin1String("RegexTest_1386") + << QLatin1String("RegexTest_1387") + << QLatin1String("RegexTest_1388") + << QLatin1String("RegexTest_1389") + << QLatin1String("RegexTest_1390") + << QLatin1String("RegexTest_1391") + << QLatin1String("RegexTest_1392") + << QLatin1String("RegexTest_1393") + << QLatin1String("RegexTest_1394") + << QLatin1String("RegexTest_1395") + << QLatin1String("RegexTest_1396") + << QLatin1String("RegexTest_1397") + << QLatin1String("RegexTest_1398") + << QLatin1String("RegexTest_1399") + << QLatin1String("RegexTest_1400") + << QLatin1String("RegexTest_1401") + << QLatin1String("RegexTest_1402") + << QLatin1String("RegexTest_1403") + << QLatin1String("RegexTest_1404") + << QLatin1String("RegexTest_1405") + << QLatin1String("RegexTest_1406") + << QLatin1String("RegexTest_1407") + << QLatin1String("RegexTest_1408") + << QLatin1String("RegexTest_1409") + << QLatin1String("RegexTest_1410") + << QLatin1String("RegexTest_1412") + << QLatin1String("RegexTest_1413") + << QLatin1String("RegexTest_1414") + << QLatin1String("RegexTest_1420") + << QLatin1String("RegexTest_1421") + << QLatin1String("RegexTest_1422") + << QLatin1String("RegexTest_1423") + << QLatin1String("RegexTest_1424") + << QLatin1String("RegexTest_1425") + << QLatin1String("RegexTest_1426") + << QLatin1String("RegexTest_1427") + << QLatin1String("RegexTest_1428") + << QLatin1String("RegexTest_1429") + << QLatin1String("RegexTest_1430") + << QLatin1String("RegexTest_1433") + << QLatin1String("RegexTest_1434") + << QLatin1String("RegexTest_1435") + << QLatin1String("RegexTest_1436") + << QLatin1String("RegexTest_1437") + << QLatin1String("RegexTest_1438") + << QLatin1String("RegexTest_1439") + << QLatin1String("RegexTest_1440") + << QLatin1String("RegexTest_1441") + << QLatin1String("RegexTest_1442") + << QLatin1String("RegexTest_1443") + << QLatin1String("RegexTest_1444") + << QLatin1String("RegexTest_1445") + << QLatin1String("RegexTest_1446") + << QLatin1String("RegexTest_1447") + << QLatin1String("RegexTest_1448") + << QLatin1String("RegexTest_1451") + << QLatin1String("RegexTest_1452") + << QLatin1String("RegexTest_1453") + << QLatin1String("RegexTest_1454") + << QLatin1String("RegexTest_1455") + << QLatin1String("RegexTest_1456") + << QLatin1String("RegexTest_1472") + << QLatin1String("RegexTest_1473") + << QLatin1String("RegexTest_1474") + << QLatin1String("RegexTest_1475") + << QLatin1String("RegexTest_1478") + << QLatin1String("RegexTest_1479") + << QLatin1String("RegexTest_1480") + << QLatin1String("RegexTest_1481") + << QLatin1String("RegexTest_1484") + << QLatin1String("RegexTest_1485") + << QLatin1String("RegexTest_1486") + << QLatin1String("RegexTest_1487") + << QLatin1String("RegexTest_1488") + << QLatin1String("RegexTest_1491") + << QLatin1String("RegexTest_1492") + << QLatin1String("RegexTest_1493") + << QLatin1String("RegexTest_1494") + << QLatin1String("RegexTest_1495") + << QLatin1String("RegexTest_1496") + << QLatin1String("RegexTest_1497") + << QLatin1String("RegexTest_1498") + << QLatin1String("RegexTest_1499") + << QLatin1String("RegexTest_1500") + << QLatin1String("RegexTest_1501") + << QLatin1String("RegexTest_1502") + << QLatin1String("RegexTest_1503") + << QLatin1String("RegexTest_1543") + << QLatin1String("RegexTest_1544") + << QLatin1String("reZ001") +*/ + << QLatin1String("schA2") + << QLatin1String("schA5") + << QLatin1String("schA7") + << QLatin1String("schD8") + << QLatin1String("schG3") + << QLatin1String("schG6") + << QLatin1String("schG9") + << QLatin1String("schG11") + << QLatin1String("schG12") + << QLatin1String("schU1") + << QLatin1String("schU3") + << QLatin1String("schU4") + << QLatin1String("schU5") + << QLatin1String("schZ004") + << QLatin1String("schZ005") + << QLatin1String("schZ012_a") + << QLatin1String("stZ041") + << QLatin1String("wildZ010"); +} + +bool XSDTestSuiteHandler::startElement(const QString &namespaceURI, + const QString &localName, + const QString &/*qName*/, + const QXmlAttributes &atts) +{ + if(namespaceURI != QString::fromLatin1("http://www.w3.org/XML/2004/xml-schema-test-suite/")) + return true; + + if (localName == QLatin1String("testSet")) { + m_currentTestSet = new TestGroup(m_topLevelGroup); + Q_ASSERT(m_currentTestSet); + m_currentTestSet->setTitle(atts.value("name")); + m_topLevelGroup->appendChild(m_currentTestSet); + } else if (localName == QLatin1String("testGroup")) { + m_currentTestGroup = new TestGroup(m_currentTestSet); + Q_ASSERT(m_currentTestGroup); + m_currentTestGroup->setTitle(atts.value("name")); + m_currentTestSet->appendChild(m_currentTestGroup); + m_inTestGroup = true; + } else if (localName == QLatin1String("schemaTest")) { + if (m_blackList.contains(atts.value("name"))) { + m_currentTestCase = 0; + m_schemaBlacklisted = true; + return true; + } + m_schemaBlacklisted = false; + + m_currentTestCase = new XSDTSTestCase(TestCase::Standard, m_currentTestGroup, XSDTSTestCase::SchemaTest); + Q_ASSERT(m_currentTestCase); + m_counter++; + m_currentTestCase->setName(QString::number(m_counter) + atts.value("name")); + m_currentTestGroup->appendChild(m_currentTestCase); + m_currentTestCase->setParent(m_currentTestGroup); + + m_inSchemaTest = true; + } else if (localName == QLatin1String("instanceTest")) { + if (m_schemaBlacklisted) { + m_currentTestCase = 0; + return true; + } + + m_currentTestCase = new XSDTSTestCase(TestCase::Standard, m_currentTestGroup, XSDTSTestCase::InstanceTest); + Q_ASSERT(m_currentTestCase); + m_counter++; + m_currentTestCase->setName(QString::number(m_counter) + atts.value("name")); + m_currentTestGroup->appendChild(m_currentTestCase); + + m_inInstanceTest = true; + } else if (localName == QLatin1String("schemaDocument") || localName == QLatin1String("instanceDocument")) { + if (m_inSchemaTest) { + m_currentTestCase->setSchemaUri(QUrl(atts.value("xlink:href"))); + if (m_currentSchemaLink.isEmpty()) // we only use the first schema document for validation + m_currentSchemaLink = atts.value("xlink:href"); + } + if (m_inInstanceTest) { + m_currentTestCase->setInstanceUri(QUrl(atts.value("xlink:href"))); + m_currentTestCase->setSchemaUri(QUrl(m_currentSchemaLink)); + } + } else if (localName == QLatin1String("expected") && (m_inSchemaTest || m_inInstanceTest)) { + TestBaseLine *baseLine = new TestBaseLine(TestBaseLine::SchemaIsValid); + if (atts.value("validity") == QLatin1String("valid")) { + baseLine->setDetails(QLatin1String("true")); + m_currentTestCase->setName(m_currentTestCase->name() + QLatin1String(" tokoe:valid")); + } else { + baseLine->setDetails(QLatin1String("false")); + m_currentTestCase->setName(m_currentTestCase->name() + QLatin1String(" tokoe:invalid")); + } + + m_currentTestCase->addBaseLine(baseLine); + } else if (localName == QLatin1String("documentation") && m_inTestGroup) { + m_inDescription = true; + } + + return true; +} + +bool XSDTestSuiteHandler::endElement(const QString &namespaceURI, + const QString &localName, + const QString &/*qName*/) +{ + if (localName == QLatin1String("testGroup")) { + m_inTestGroup = false; + m_currentTestGroup->setDescription(m_documentation); + m_documentation.clear(); + m_currentSchemaLink.clear(); + + if (m_currentTestGroup->childCount() == 0) + m_currentTestSet->removeLast(); + } else if (localName == QLatin1String("schemaTest")) + m_inSchemaTest = false; + else if (localName == QLatin1String("instanceTest")) + m_inInstanceTest = false; + else if (localName == QLatin1String("documentation")) + m_inDescription = false; + + return true; +} + +bool XSDTestSuiteHandler::characters(const QString &ch) +{ + if (m_inDescription) + m_documentation += ch; + + return true; +} + +TestSuite *XSDTestSuiteHandler::testSuite() const +{ + return m_ts; +} + +// vim: et:ts=4:sw=4:sts=4 + diff --git a/tests/auto/xmlpatternsxqts/lib/XSDTestSuiteHandler.h b/tests/auto/xmlpatternsxqts/lib/XSDTestSuiteHandler.h new file mode 100644 index 0000000..8c57e82 --- /dev/null +++ b/tests/auto/xmlpatternsxqts/lib/XSDTestSuiteHandler.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Patternist project on Trolltech Labs. +** +** $TROLLTECH_GPL_LICENSE$ +** +*************************************************************************** +*/ + +#ifndef PatternistSDK_XSDTestSuiteHandler_H +#define PatternistSDK_XSDTestSuiteHandler_H + +#include +#include + +#include "ExternalSourceLoader.h" +#include "TestSuite.h" +#include "XQTSTestCase.h" + +QT_BEGIN_HEADER + +namespace QPatternistSDK +{ + class TestBaseLine; + class TestGroup; + class XSDTSTestCase; + + /** + * @short Creates a TestSuite from the XSD Test Suite. + * + * The created TestSuite can be retrieved via testSuite(). + * + * @note XSDTestSuiteHandler assumes the XML is valid by having been validated + * against the W3C XML Schema. It has no safety checks for that the XML format + * is correct but is hard coded for it. Thus, the behavior is undefined if + * the XML is invalid. + * + * @ingroup PatternistSDK + * @author Tobias Koenig + */ + class Q_PATTERNISTSDK_EXPORT XSDTestSuiteHandler : public QXmlDefaultHandler + { + public: + /** + * @param catalogFile the URI for the catalog file being parsed. This + * URI is used for creating absolute URIs for files mentioned in + * the catalog with relative URIs. + * @param useExclusionList whether excludeTestGroups.txt should be used to ignore + * test groups when loading + */ + XSDTestSuiteHandler(const QUrl &catalogFile); + virtual bool characters(const QString &ch); + + virtual bool endElement(const QString &namespaceURI, + const QString &localName, + const QString &qName); + virtual bool startElement(const QString &namespaceURI, + const QString &localName, + const QString &qName, + const QXmlAttributes &atts); + + virtual TestSuite *testSuite() const; + + private: + TestSuite* m_ts; + const QUrl m_catalogFile; + + TestGroup* m_topLevelGroup; + TestGroup* m_currentTestSet; + TestGroup* m_currentTestGroup; + XSDTSTestCase* m_currentTestCase; + bool m_inSchemaTest; + bool m_inInstanceTest; + bool m_inTestGroup; + bool m_inDescription; + bool m_schemaBlacklisted; + QString m_documentation; + QString m_currentSchemaLink; + int m_counter; + QSet m_blackList; + }; +} + +QT_END_HEADER + +#endif +// vim: et:ts=4:sw=4:sts=4 diff --git a/tests/auto/xmlpatternsxqts/lib/lib.pro b/tests/auto/xmlpatternsxqts/lib/lib.pro index 5b12d63..cb9453a 100644 --- a/tests/auto/xmlpatternsxqts/lib/lib.pro +++ b/tests/auto/xmlpatternsxqts/lib/lib.pro @@ -50,6 +50,8 @@ HEADERS = ASTItem.h \ Worker.h \ XMLWriter.h \ XQTSTestCase.h \ + XSDTestSuiteHandler.h \ + XSDTSTestCase.h \ XSLTTestSuiteHandler.h SOURCES = ASTItem.cpp \ @@ -75,4 +77,6 @@ SOURCES = ASTItem.cpp \ Worker.cpp \ XMLWriter.cpp \ XQTSTestCase.cpp \ + XSDTestSuiteHandler.cpp \ + XSDTSTestCase.cpp \ XSLTTestSuiteHandler.cpp diff --git a/tests/auto/xmlpatternsxqts/test/tst_suitetest.cpp b/tests/auto/xmlpatternsxqts/test/tst_suitetest.cpp index 1f9e396..71abbb9 100644 --- a/tests/auto/xmlpatternsxqts/test/tst_suitetest.cpp +++ b/tests/auto/xmlpatternsxqts/test/tst_suitetest.cpp @@ -55,11 +55,11 @@ using namespace QPatternistSDK; -tst_SuiteTest::tst_SuiteTest(const bool isXSLT, +tst_SuiteTest::tst_SuiteTest(const SuiteType suiteType, const bool alwaysRun) : m_existingBaseline(inputFile(QLatin1String("Baseline.xml"))) , m_candidateBaseline(inputFile(QLatin1String("CandidateBaseline.xml"))) , m_abortRun(!alwaysRun && !QFile::exists(QLatin1String("runTests"))) - , m_isXSLT(isXSLT) + , m_suiteType(suiteType) { } @@ -86,7 +86,16 @@ void tst_SuiteTest::runTestSuite() const QString errMsg; const QFileInfo fi(m_catalogPath); const QUrl catalogPath(QUrl::fromLocalFile(fi.absoluteFilePath())); - TestSuite *const ts = TestSuite::openCatalog(catalogPath, errMsg, true, m_isXSLT); + + TestSuite::SuiteType suiteType; + switch (m_suiteType) { + case XQuerySuite: suiteType = TestSuite::XQuerySuite; + case XsltSuite: suiteType = TestSuite::XsltSuite; + case XsdSuite: suiteType = TestSuite::XsdSuite; + default: break; + } + + TestSuite *const ts = TestSuite::openCatalog(catalogPath, errMsg, true, suiteType); QVERIFY2(ts, qPrintable(QString::fromLatin1("Failed to open the catalog, maybe it doesn't exist or is broken: %1").arg(errMsg))); diff --git a/tests/auto/xmlpatternsxqts/test/tst_suitetest.h b/tests/auto/xmlpatternsxqts/test/tst_suitetest.h index 922f645..05bf6cb 100644 --- a/tests/auto/xmlpatternsxqts/test/tst_suitetest.h +++ b/tests/auto/xmlpatternsxqts/test/tst_suitetest.h @@ -50,13 +50,21 @@ \class tst_SuiteTest \internal \since 4.5 - \brief Base class for tst_XmlPatternsXQTS and tst_XmlPatternsXSLTS. + \brief Base class for tst_XmlPatternsXQTS, tst_XmlPatternsXSLTS and tst_XmlPatternsXSDTS. */ class tst_SuiteTest : public QObject , private TestFundament { Q_OBJECT +public: + enum SuiteType + { + XQuerySuite, + XsltSuite, + XsdSuite + }; + protected: /** * @p isXSLT is @c true if the catalog opened is an @@ -65,7 +73,7 @@ protected: * @p alwaysRun is @c true if the test should always be run, * regardless of if the file runTests exists. */ - tst_SuiteTest(const bool isXSLT, + tst_SuiteTest(SuiteType type, const bool alwaysRun = false); /** @@ -91,7 +99,7 @@ private: const QString m_existingBaseline; const QString m_candidateBaseline; const bool m_abortRun; - const bool m_isXSLT; + const SuiteType m_suiteType; }; #endif diff --git a/tests/auto/xmlpatternsxqts/test/tst_xmlpatternsxqts.cpp b/tests/auto/xmlpatternsxqts/test/tst_xmlpatternsxqts.cpp index 6d9502d..1193372 100644 --- a/tests/auto/xmlpatternsxqts/test/tst_xmlpatternsxqts.cpp +++ b/tests/auto/xmlpatternsxqts/test/tst_xmlpatternsxqts.cpp @@ -61,7 +61,7 @@ public: virtual void catalogPath(QString &write) const; }; -tst_XmlPatternsXQTS::tst_XmlPatternsXQTS() : tst_SuiteTest(false) +tst_XmlPatternsXQTS::tst_XmlPatternsXQTS() : tst_SuiteTest(tst_SuiteTest::XQuerySuite) { } diff --git a/tests/auto/xmlpatternsxslts/tst_xmlpatternsxslts.cpp b/tests/auto/xmlpatternsxslts/tst_xmlpatternsxslts.cpp index 6f1d217..f9b1c76 100644 --- a/tests/auto/xmlpatternsxslts/tst_xmlpatternsxslts.cpp +++ b/tests/auto/xmlpatternsxslts/tst_xmlpatternsxslts.cpp @@ -61,7 +61,7 @@ protected: virtual void catalogPath(QString &write) const; }; -tst_XmlPatternsXSLTS::tst_XmlPatternsXSLTS() : tst_SuiteTest(true) +tst_XmlPatternsXSLTS::tst_XmlPatternsXSLTS() : tst_SuiteTest(tst_SuiteTest::XsltSuite) { } diff --git a/tools/tools.pro b/tools/tools.pro index 0a56cfb..e7f7b03 100644 --- a/tools/tools.pro +++ b/tools/tools.pro @@ -25,7 +25,7 @@ mac { SUBDIRS += kmap2qmap contains(QT_CONFIG, dbus):SUBDIRS += qdbus -!wince*:contains(QT_CONFIG, xmlpatterns): SUBDIRS += xmlpatterns +!wince*:contains(QT_CONFIG, xmlpatterns): SUBDIRS += xmlpatterns xmlpatternsvalidator embedded: SUBDIRS += makeqpf CONFIG+=ordered diff --git a/tools/xmlpatternsvalidator/main.cpp b/tools/xmlpatternsvalidator/main.cpp new file mode 100644 index 0000000..032afc0 --- /dev/null +++ b/tools/xmlpatternsvalidator/main.cpp @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the Patternist project on Trolltech Labs. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "main.h" + +#include +#include +#include +#include +#include + +QT_USE_NAMESPACE + +enum ExecutionMode +{ + InvalidMode, + SchemaOnlyMode, + SchemaAndInstanceMode, + InstanceOnlyMode +}; + +int main(int argc, char **argv) +{ + const QCoreApplication app(argc, argv); + QCoreApplication::setApplicationName(QLatin1String("xmlpatternsvalidator")); + + if (argc != 2 && argc != 3) { + qDebug() << QXmlPatternistCLI::tr("usage: xmlpatternsvalidator ( | | )"); + return 2; + } + + // parse command line arguments + ExecutionMode mode = InvalidMode; + + if (argc == 2) { + // either it is a schema or instance document + + QString url = QFile::decodeName(argv[1]); + if (url.toLower().endsWith(QLatin1String(".xsd"))) { + mode = SchemaOnlyMode; + } else { + // as we could validate all types of xml documents, don't check the extension here + mode = InstanceOnlyMode; + } + } else if (argc == 3) { + mode = SchemaAndInstanceMode; + } + + // do validation + QXmlSchema schema; + + if (mode == SchemaOnlyMode) { + const QString schemaUri = QFile::decodeName(argv[1]); + + schema.load(QUrl(schemaUri)); + + if (schema.isValid()) + return 0; + else + return 1; + } else if (mode == SchemaAndInstanceMode) { + const QString instanceUri = QFile::decodeName(argv[1]); + const QString schemaUri = QFile::decodeName(argv[2]); + + schema.load(QUrl(schemaUri)); + + if (!schema.isValid()) + return 1; + + QXmlSchemaValidator validator(schema); + if (validator.validate(QUrl(instanceUri))) + return 0; + else + return 1; + } else if (mode == InstanceOnlyMode) { + const QString instanceUri = QFile::decodeName(argv[1]); + + QXmlSchemaValidator validator(schema); + if (validator.validate(QUrl(instanceUri))) + return 0; + else + return 1; + } + + Q_ASSERT(false); + + return 1; +} diff --git a/tools/xmlpatternsvalidator/main.h b/tools/xmlpatternsvalidator/main.h new file mode 100644 index 0000000..477a45a --- /dev/null +++ b/tools/xmlpatternsvalidator/main.h @@ -0,0 +1,46 @@ +/**************************************************************************** + ** + ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). + ** Contact: Qt Software Information (qt-info@nokia.com) + ** + ** This file is part of the Patternist project on Trolltech Labs. * ** + ** $TROLLTECH_DUAL_LICENSE$ + ** + ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE + ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + ** + ****************************************************************************/ + +// +// 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. + +#ifndef Patternist_main_h +#define Patternist_main_h + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QXmlPatternistCLI +{ +public: + Q_DECLARE_TR_FUNCTIONS(QXmlPatternistCLI) +private: + inline QXmlPatternistCLI(); + Q_DISABLE_COPY(QXmlPatternistCLI) +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/tools/xmlpatternsvalidator/xmlpatternsvalidator.pro b/tools/xmlpatternsvalidator/xmlpatternsvalidator.pro new file mode 100644 index 0000000..dd5bd37 --- /dev/null +++ b/tools/xmlpatternsvalidator/xmlpatternsvalidator.pro @@ -0,0 +1,19 @@ +TEMPLATE = app +TARGET = xmlpatternsvalidator +DESTDIR = ../../bin +QT -= gui +QT += xmlpatterns + +target.path = $$[QT_INSTALL_BINS] +INSTALLS += target + +# This ensures we get stderr and stdout on Windows. +CONFIG += console + +# This ensures that this is a command-line program on OS X and not a GUI application. +CONFIG -= app_bundle + +SOURCES = main.cpp +HEADERS = main.h + +include(../src/common.pri) -- cgit v0.12 From 456463169c6d00b9938f0d975dbd7f398edea39d Mon Sep 17 00:00:00 2001 From: Tobias Koenig Date: Sat, 16 May 2009 12:30:25 +0200 Subject: Various api, documentation and code cleanups --- src/xmlpatterns/api/qxmlquery.cpp | 6 +- src/xmlpatterns/api/qxmlquery_p.h | 13 -- src/xmlpatterns/api/qxmlschema.cpp | 19 +- src/xmlpatterns/api/qxmlschema.h | 11 +- src/xmlpatterns/api/qxmlschema_p.cpp | 8 +- src/xmlpatterns/api/qxmlschema_p.h | 6 +- src/xmlpatterns/api/qxmlschemavalidator.cpp | 38 +++- src/xmlpatterns/api/qxmlschemavalidator.h | 13 +- src/xmlpatterns/api/qxmlschemavalidator_p.h | 5 +- src/xmlpatterns/schema/qnamespacesupport.cpp | 4 +- src/xmlpatterns/schema/qxsdparticlechecker.cpp | 6 +- src/xmlpatterns/schema/qxsdschemacontext.cpp | 2 +- src/xmlpatterns/schema/qxsdschemacontext_p.h | 4 +- src/xmlpatterns/schema/qxsdschemadebugger_p.h | 2 +- src/xmlpatterns/schema/qxsdschemahelper.cpp | 4 +- src/xmlpatterns/schema/qxsdschemahelper_p.h | 63 +++++-- src/xmlpatterns/schema/qxsdschemaparser.cpp | 46 +++-- src/xmlpatterns/schema/qxsdstatemachine.cpp | 16 +- src/xmlpatterns/schema/qxsdstatemachine_p.h | 6 + .../schema/qxsdvalidatedxmlnodemodel.cpp | 2 +- .../schema/qxsdvalidatedxmlnodemodel_p.h | 10 +- .../schema/qxsdvalidatinginstancereader.cpp | 15 +- .../schema/qxsdvalidatinginstancereader_p.h | 2 +- src/xmlpatterns/utils/qxpathhelper.cpp | 12 ++ src/xmlpatterns/utils/qxpathhelper_p.h | 5 + .../patternistheaders/tst_patternistheaders.cpp | 8 + tests/auto/qxmlschema/tst_qxmlschema.cpp | 195 ++++++++++++++++++--- .../tst_qxmlschemavalidator.cpp | 145 +++++++++++---- tools/xmlpatternsvalidator/main.cpp | 41 +++-- 29 files changed, 521 insertions(+), 186 deletions(-) diff --git a/src/xmlpatterns/api/qxmlquery.cpp b/src/xmlpatterns/api/qxmlquery.cpp index 423da3e..1cf0a2e 100644 --- a/src/xmlpatterns/api/qxmlquery.cpp +++ b/src/xmlpatterns/api/qxmlquery.cpp @@ -427,7 +427,7 @@ void QXmlQuery::setQuery(QIODevice *sourceCode, const QUrl &documentURI) return; } - d->queryURI = QXmlQueryPrivate::normalizeQueryURI(documentURI); + d->queryURI = QPatternist::XPathHelper::normalizeQueryURI(documentURI); d->expression(sourceCode); } @@ -475,12 +475,12 @@ void QXmlQuery::setQuery(const QUrl &queryURI, const QUrl &baseURI) { Q_ASSERT_X(queryURI.isValid(), Q_FUNC_INFO, "The passed URI must be valid."); - const QUrl canonicalURI(QXmlQueryPrivate::normalizeQueryURI(queryURI)); + const QUrl canonicalURI(QPatternist::XPathHelper::normalizeQueryURI(queryURI)); Q_ASSERT(canonicalURI.isValid()); Q_ASSERT(!canonicalURI.isRelative()); Q_ASSERT(baseURI.isValid() || baseURI.isEmpty()); - d->queryURI = QXmlQueryPrivate::normalizeQueryURI(baseURI.isEmpty() ? queryURI : baseURI); + d->queryURI = QPatternist::XPathHelper::normalizeQueryURI(baseURI.isEmpty() ? queryURI : baseURI); QPatternist::AutoPtr result; diff --git a/src/xmlpatterns/api/qxmlquery_p.h b/src/xmlpatterns/api/qxmlquery_p.h index 7f58f97..486d885 100644 --- a/src/xmlpatterns/api/qxmlquery_p.h +++ b/src/xmlpatterns/api/qxmlquery_p.h @@ -212,19 +212,6 @@ public: return m_resourceLoader; } - - static inline QUrl normalizeQueryURI(const QUrl &uri) - { - Q_ASSERT_X(uri.isEmpty() || uri.isValid(), Q_FUNC_INFO, - "The URI passed to QXmlQuery::setQuery() must be valid or empty."); - if(uri.isEmpty()) - return QUrl::fromLocalFile(QCoreApplication::applicationFilePath()); - else if(uri.isRelative()) - return QUrl::fromLocalFile(QCoreApplication::applicationFilePath()).resolved(uri); - else - return uri; - } - void setRequiredType(const QPatternist::SequenceType::Ptr &seqType) { Q_ASSERT(seqType); diff --git a/src/xmlpatterns/api/qxmlschema.cpp b/src/xmlpatterns/api/qxmlschema.cpp index 55b96cd..108212e 100644 --- a/src/xmlpatterns/api/qxmlschema.cpp +++ b/src/xmlpatterns/api/qxmlschema.cpp @@ -21,7 +21,7 @@ \brief The QXmlSchema class provides loading and validation of a W3C XML Schema. \reentrant - \since 4.X + \since 4.6 \ingroup xml-tools The QXmlSchema class loads, compiles and validates W3C XML Schema files @@ -31,7 +31,7 @@ /*! Constructs an invalid, empty schema that cannot be used until - setSchema() is called. + load() is called. */ QXmlSchema::QXmlSchema() : d(new QXmlSchemaPrivate(QXmlNamePool())) @@ -59,9 +59,10 @@ QXmlSchema::~QXmlSchema() Sets this QXmlSchema to a schema loaded from the \a source URI. */ -void QXmlSchema::load(const QUrl &source) +bool QXmlSchema::load(const QUrl &source) { d->load(source, QString()); + return d->isValid(); } /*! @@ -78,9 +79,10 @@ void QXmlSchema::load(const QUrl &source) a valid URI, behavior is undefined. \sa isValid() */ -void QXmlSchema::load(QIODevice *source, const QUrl &documentUri) +bool QXmlSchema::load(QIODevice *source, const QUrl &documentUri) { d->load(source, documentUri, QString()); + return d->isValid(); } /*! @@ -94,9 +96,10 @@ void QXmlSchema::load(QIODevice *source, const QUrl &documentUri) If \a documentUri is not a valid URI, behavior is undefined. \sa isValid() */ -void QXmlSchema::load(const QByteArray &data, const QUrl &documentUri) +bool QXmlSchema::load(const QByteArray &data, const QUrl &documentUri) { d->load(data, documentUri, QString()); + return d->isValid(); } /*! @@ -183,14 +186,14 @@ QAbstractMessageHandler *QXmlSchema::messageHandler() const \sa uriResolver() */ -void QXmlSchema::setUriResolver(QAbstractUriResolver *resolver) +void QXmlSchema::setUriResolver(const QAbstractUriResolver *resolver) { d->setUriResolver(resolver); } /*! Returns the schema's URI resolver. If no URI resolver has been set, - QtXmlPatterns will use the URIs in queries as they are. + QtXmlPatterns will use the URIs in schemas as they are. The URI resolver provides a level of abstraction, or \e{polymorphic URIs}. A resolver can rewrite \e{logical} URIs to physical ones, or @@ -202,7 +205,7 @@ void QXmlSchema::setUriResolver(QAbstractUriResolver *resolver) \sa setUriResolver() */ -QAbstractUriResolver *QXmlSchema::uriResolver() const +const QAbstractUriResolver *QXmlSchema::uriResolver() const { return d->uriResolver(); } diff --git a/src/xmlpatterns/api/qxmlschema.h b/src/xmlpatterns/api/qxmlschema.h index 225cce2..cf56b1e 100644 --- a/src/xmlpatterns/api/qxmlschema.h +++ b/src/xmlpatterns/api/qxmlschema.h @@ -13,6 +13,7 @@ #define QXMLSCHEMA_H #include +#include #include QT_BEGIN_HEADER @@ -37,9 +38,9 @@ class Q_XMLPATTERNS_EXPORT QXmlSchema QXmlSchema(const QXmlSchema &other); ~QXmlSchema(); - void load(const QUrl &source); - void load(QIODevice *source, const QUrl &documentUri); - void load(const QByteArray &data, const QUrl &documentUri); + bool load(const QUrl &source); + bool load(QIODevice *source, const QUrl &documentUri = QUrl()); + bool load(const QByteArray &data, const QUrl &documentUri = QUrl()); bool isValid() const; @@ -49,8 +50,8 @@ class Q_XMLPATTERNS_EXPORT QXmlSchema void setMessageHandler(QAbstractMessageHandler *handler); QAbstractMessageHandler *messageHandler() const; - void setUriResolver(QAbstractUriResolver *resolver); - QAbstractUriResolver *uriResolver() const; + void setUriResolver(const QAbstractUriResolver *resolver); + const QAbstractUriResolver *uriResolver() const; void setNetworkAccessManager(QNetworkAccessManager *networkmanager); QNetworkAccessManager *networkAccessManager() const; diff --git a/src/xmlpatterns/api/qxmlschema_p.cpp b/src/xmlpatterns/api/qxmlschema_p.cpp index ebcccee..21dc04a 100644 --- a/src/xmlpatterns/api/qxmlschema_p.cpp +++ b/src/xmlpatterns/api/qxmlschema_p.cpp @@ -61,7 +61,7 @@ QXmlSchemaPrivate::QXmlSchemaPrivate(const QXmlSchemaPrivate &other) void QXmlSchemaPrivate::load(const QUrl &source, const QString &targetNamespace) { - m_documentUri = source; + m_documentUri = QPatternist::XPathHelper::normalizeQueryURI(source); m_schemaContext->setMessageHandler(messageHandler()); m_schemaContext->setUriResolver(uriResolver()); @@ -98,7 +98,7 @@ void QXmlSchemaPrivate::load(QIODevice *source, const QUrl &documentUri, const Q return; } - m_documentUri = documentUri; + m_documentUri = QPatternist::XPathHelper::normalizeQueryURI(documentUri); m_schemaContext->setMessageHandler(messageHandler()); m_schemaContext->setUriResolver(uriResolver()); m_schemaContext->setNetworkAccessManager(networkAccessManager()); @@ -145,12 +145,12 @@ QAbstractMessageHandler *QXmlSchemaPrivate::messageHandler() const return m_messageHandler.data()->value; } -void QXmlSchemaPrivate::setUriResolver(QAbstractUriResolver *resolver) +void QXmlSchemaPrivate::setUriResolver(const QAbstractUriResolver *resolver) { m_uriResolver = resolver; } -QAbstractUriResolver *QXmlSchemaPrivate::uriResolver() const +const QAbstractUriResolver *QXmlSchemaPrivate::uriResolver() const { return m_uriResolver; } diff --git a/src/xmlpatterns/api/qxmlschema_p.h b/src/xmlpatterns/api/qxmlschema_p.h index e625f1e..efba256 100644 --- a/src/xmlpatterns/api/qxmlschema_p.h +++ b/src/xmlpatterns/api/qxmlschema_p.h @@ -54,14 +54,14 @@ class QXmlSchemaPrivate : public QSharedData QUrl documentUri() const; void setMessageHandler(QAbstractMessageHandler *handler); QAbstractMessageHandler *messageHandler() const; - void setUriResolver(QAbstractUriResolver *resolver); - QAbstractUriResolver *uriResolver() const; + void setUriResolver(const QAbstractUriResolver *resolver); + const QAbstractUriResolver *uriResolver() const; void setNetworkAccessManager(QNetworkAccessManager *networkmanager); QNetworkAccessManager *networkAccessManager() const; QXmlNamePool m_namePool; QAbstractMessageHandler* m_userMessageHandler; - QAbstractUriResolver* m_uriResolver; + const QAbstractUriResolver* m_uriResolver; QNetworkAccessManager* m_userNetworkAccessManager; QPatternist::ReferenceCountedValue::Ptr m_messageHandler; QPatternist::ReferenceCountedValue::Ptr m_networkAccessManager; diff --git a/src/xmlpatterns/api/qxmlschemavalidator.cpp b/src/xmlpatterns/api/qxmlschemavalidator.cpp index aa80537..fcde49c 100644 --- a/src/xmlpatterns/api/qxmlschemavalidator.cpp +++ b/src/xmlpatterns/api/qxmlschemavalidator.cpp @@ -27,7 +27,7 @@ \brief The QXmlSchemaValidator class validates XML instance documents against a W3C XML Schema. \reentrant - \since 4.X + \since 4.6 \ingroup xml-tools The QXmlSchemaValidator class loads, parses an XML instance document and validates it @@ -35,6 +35,16 @@ */ /*! + Constructs a schema validator. + The schema used for validation must be referenced in the XML instance document + via the xsi:schemaLocation attribute. + */ +QXmlSchemaValidator::QXmlSchemaValidator() + : d(new QXmlSchemaValidatorPrivate(QXmlSchema())) +{ +} + +/*! Constructs a schema validator that will use \a schema for validation. */ QXmlSchemaValidator::QXmlSchemaValidator(const QXmlSchema &schema) @@ -65,7 +75,7 @@ void QXmlSchemaValidator::setSchema(const QXmlSchema &schema) Returns \c true if the XML instance document is valid according the schema, \c false otherwise. */ -bool QXmlSchemaValidator::validate(const QByteArray &data, const QUrl &documentUri) +bool QXmlSchemaValidator::validate(const QByteArray &data, const QUrl &documentUri) const { QByteArray localData(data); @@ -81,7 +91,7 @@ bool QXmlSchemaValidator::validate(const QByteArray &data, const QUrl &documentU Returns \c true if the XML instance document is valid according the schema, \c false otherwise. */ -bool QXmlSchemaValidator::validate(const QUrl &source) +bool QXmlSchemaValidator::validate(const QUrl &source) const { d->m_context->setMessageHandler(messageHandler()); d->m_context->setUriResolver(uriResolver()); @@ -102,7 +112,7 @@ bool QXmlSchemaValidator::validate(const QUrl &source) Returns \c true if the XML instance document is valid according the schema, \c false otherwise. */ -bool QXmlSchemaValidator::validate(QIODevice *source, const QUrl &documentUri) +bool QXmlSchemaValidator::validate(QIODevice *source, const QUrl &documentUri) const { if (!source) { qWarning("A null QIODevice pointer cannot be passed."); @@ -114,6 +124,8 @@ bool QXmlSchemaValidator::validate(QIODevice *source, const QUrl &documentUri) return false; } + const QUrl normalizedUri = QPatternist::XPathHelper::normalizeQueryURI(documentUri); + d->m_context->setMessageHandler(messageHandler()); d->m_context->setUriResolver(uriResolver()); d->m_context->setNetworkAccessManager(networkAccessManager()); @@ -125,7 +137,7 @@ bool QXmlSchemaValidator::validate(QIODevice *source, const QUrl &documentUri) QPatternist::Item item; try { - item = loader.openDocument(source, documentUri, d->m_context); + item = loader.openDocument(source, normalizedUri, d->m_context); } catch (QPatternist::Exception exception) { return false; } @@ -135,7 +147,7 @@ bool QXmlSchemaValidator::validate(QIODevice *source, const QUrl &documentUri) QPatternist::XsdValidatedXmlNodeModel *validatedModel = new QPatternist::XsdValidatedXmlNodeModel(model); - QPatternist::XsdValidatingInstanceReader reader(validatedModel, documentUri, d->m_context); + QPatternist::XsdValidatingInstanceReader reader(validatedModel, normalizedUri, d->m_context); if (d->m_schema) reader.addSchema(d->m_schema, d->m_schemaDocumentUri); try { @@ -158,6 +170,14 @@ QXmlNamePool QXmlSchemaValidator::namePool() const } /*! + Returns the schema that is used for validation. + */ +QXmlSchema QXmlSchemaValidator::schema() const +{ + return d->m_originalSchema; +} + +/*! Changes the \l {QAbstractMessageHandler}{message handler} for this QXmlSchemaValidator to \a handler. The schema validator sends all parsing and validation messages to this message handler. QXmlSchemaValidator does not take @@ -215,14 +235,14 @@ QAbstractMessageHandler *QXmlSchemaValidator::messageHandler() const \sa uriResolver() */ -void QXmlSchemaValidator::setUriResolver(QAbstractUriResolver *resolver) +void QXmlSchemaValidator::setUriResolver(const QAbstractUriResolver *resolver) { d->m_uriResolver = resolver; } /*! Returns the schema's URI resolver. If no URI resolver has been set, - QtXmlPatterns will use the URIs in queries as they are. + QtXmlPatterns will use the URIs in instance documents as they are. The URI resolver provides a level of abstraction, or \e{polymorphic URIs}. A resolver can rewrite \e{logical} URIs to physical ones, or @@ -234,7 +254,7 @@ void QXmlSchemaValidator::setUriResolver(QAbstractUriResolver *resolver) \sa setUriResolver() */ -QAbstractUriResolver *QXmlSchemaValidator::uriResolver() const +const QAbstractUriResolver *QXmlSchemaValidator::uriResolver() const { return d->m_uriResolver; } diff --git a/src/xmlpatterns/api/qxmlschemavalidator.h b/src/xmlpatterns/api/qxmlschemavalidator.h index e643995..c82c522 100644 --- a/src/xmlpatterns/api/qxmlschemavalidator.h +++ b/src/xmlpatterns/api/qxmlschemavalidator.h @@ -12,6 +12,7 @@ #ifndef QXMLSCHEMAVALIDATOR_H #define QXMLSCHEMAVALIDATOR_H +#include #include QT_BEGIN_HEADER @@ -31,22 +32,24 @@ class QXmlSchemaValidatorPrivate; class Q_XMLPATTERNS_EXPORT QXmlSchemaValidator { public: + QXmlSchemaValidator(); QXmlSchemaValidator(const QXmlSchema &schema); ~QXmlSchemaValidator(); void setSchema(const QXmlSchema &schema); - bool validate(const QUrl &source); - bool validate(QIODevice *source, const QUrl &documentUri); - bool validate(const QByteArray &data, const QUrl &documentUri); + bool validate(const QUrl &source) const; + bool validate(QIODevice *source, const QUrl &documentUri = QUrl()) const; + bool validate(const QByteArray &data, const QUrl &documentUri = QUrl()) const; QXmlNamePool namePool() const; + QXmlSchema schema() const; void setMessageHandler(QAbstractMessageHandler *handler); QAbstractMessageHandler *messageHandler() const; - void setUriResolver(QAbstractUriResolver *resolver); - QAbstractUriResolver *uriResolver() const; + void setUriResolver(const QAbstractUriResolver *resolver); + const QAbstractUriResolver *uriResolver() const; void setNetworkAccessManager(QNetworkAccessManager *networkmanager); QNetworkAccessManager *networkAccessManager() const; diff --git a/src/xmlpatterns/api/qxmlschemavalidator_p.h b/src/xmlpatterns/api/qxmlschemavalidator_p.h index 0990f73..9910f6e 100644 --- a/src/xmlpatterns/api/qxmlschemavalidator_p.h +++ b/src/xmlpatterns/api/qxmlschemavalidator_p.h @@ -77,15 +77,18 @@ public: m_context = QPatternist::XsdSchemaContext::Ptr(new QPatternist::XsdSchemaContext(m_namePool.d)); m_context->m_schemaTypeFactory = schema.d->m_schemaContext->m_schemaTypeFactory; m_context->m_builtinTypesFacetList = schema.d->m_schemaContext->m_builtinTypesFacetList; + + m_originalSchema = schema; } QXmlNamePool m_namePool; QAbstractMessageHandler* m_userMessageHandler; - QAbstractUriResolver* m_uriResolver; + const QAbstractUriResolver* m_uriResolver; QNetworkAccessManager* m_userNetworkAccessManager; QPatternist::ReferenceCountedValue::Ptr m_messageHandler; QPatternist::ReferenceCountedValue::Ptr m_networkAccessManager; + QXmlSchema m_originalSchema; QPatternist::XsdSchemaContext::Ptr m_context; QPatternist::XsdSchema::Ptr m_schema; QUrl m_schemaDocumentUri; diff --git a/src/xmlpatterns/schema/qnamespacesupport.cpp b/src/xmlpatterns/schema/qnamespacesupport.cpp index 00698d6..349f451 100644 --- a/src/xmlpatterns/schema/qnamespacesupport.cpp +++ b/src/xmlpatterns/schema/qnamespacesupport.cpp @@ -33,9 +33,7 @@ NamespaceSupport::NamespaceSupport(const NamePool::Ptr &namePool) : m_namePool(namePool) { // the XML namespace - const QXmlName binding = namePool->allocateBinding(QLatin1String("xml"), - QLatin1String("http://www.w3.org/XML/1998/namespace")); - m_ns.insert(binding.prefix(), binding.namespaceURI()); + m_ns.insert(StandardPrefixes::xml, StandardNamespaces::xml); } void NamespaceSupport::setPrefix(const QXmlName::PrefixCode prefixCode, const QXmlName::NamespaceCode namespaceCode) diff --git a/src/xmlpatterns/schema/qxsdparticlechecker.cpp b/src/xmlpatterns/schema/qxsdparticlechecker.cpp index 1bdef00..7a09f8a 100644 --- a/src/xmlpatterns/schema/qxsdparticlechecker.cpp +++ b/src/xmlpatterns/schema/qxsdparticlechecker.cpp @@ -180,9 +180,9 @@ static bool derivedTermValid(const XsdTerm::Ptr &baseTerm, const XsdTerm::Ptr &d // check that the constraints of the derived element are more strict then the constraints of the base element const XsdElement::BlockingConstraints baseConstraints = element->disallowedSubstitutions(); const XsdElement::BlockingConstraints derivedConstraints = derivedElement->disallowedSubstitutions(); - if ((baseConstraints & XsdElement::RestrictionConstraint) && !(derivedConstraints & XsdElement::RestrictionConstraint) || - (baseConstraints & XsdElement::ExtensionConstraint) && !(derivedConstraints & XsdElement::ExtensionConstraint) || - (baseConstraints & XsdElement::SubstitutionConstraint) && !(derivedConstraints & XsdElement::SubstitutionConstraint)) { + if (((baseConstraints & XsdElement::RestrictionConstraint) && !(derivedConstraints & XsdElement::RestrictionConstraint)) || + ((baseConstraints & XsdElement::ExtensionConstraint) && !(derivedConstraints & XsdElement::ExtensionConstraint)) || + ((baseConstraints & XsdElement::SubstitutionConstraint) && !(derivedConstraints & XsdElement::SubstitutionConstraint))) { errorMsg = QtXmlPatterns::tr("block constraints of derived element %1 must not be more weaker than in the base element").arg(formatKeyword(derivedElement->displayName(namePool))); return false; } diff --git a/src/xmlpatterns/schema/qxsdschemacontext.cpp b/src/xmlpatterns/schema/qxsdschemacontext.cpp index 57736bd..65b2e52 100644 --- a/src/xmlpatterns/schema/qxsdschemacontext.cpp +++ b/src/xmlpatterns/schema/qxsdschemacontext.cpp @@ -67,7 +67,7 @@ QSourceLocation XsdSchemaContext::locationFor(const SourceLocationReflection *co return QSourceLocation(); } -void XsdSchemaContext::setUriResolver(QAbstractUriResolver *uriResolver) +void XsdSchemaContext::setUriResolver(const QAbstractUriResolver *uriResolver) { m_uriResolver = uriResolver; } diff --git a/src/xmlpatterns/schema/qxsdschemacontext_p.h b/src/xmlpatterns/schema/qxsdschemacontext_p.h index cf52028..c3a9f15 100644 --- a/src/xmlpatterns/schema/qxsdschemacontext_p.h +++ b/src/xmlpatterns/schema/qxsdschemacontext_p.h @@ -115,7 +115,7 @@ namespace QPatternist * Sets the uri @p resolver that is used for resolving URIs in the * schema parser. */ - void setUriResolver(QAbstractUriResolver *resolver); + void setUriResolver(const QAbstractUriResolver *resolver); /** * Returns the uri resolver that is used for resolving URIs in the @@ -145,7 +145,7 @@ namespace QPatternist NamePool::Ptr m_namePool; QNetworkAccessManager* m_networkAccessManager; QUrl m_baseURI; - QAbstractUriResolver* m_uriResolver; + const QAbstractUriResolver* m_uriResolver; QAbstractMessageHandler* m_messageHandler; }; } diff --git a/src/xmlpatterns/schema/qxsdschemadebugger_p.h b/src/xmlpatterns/schema/qxsdschemadebugger_p.h index 8c12f0f..8966963 100644 --- a/src/xmlpatterns/schema/qxsdschemadebugger_p.h +++ b/src/xmlpatterns/schema/qxsdschemadebugger_p.h @@ -85,7 +85,7 @@ namespace QPatternist void dumpSchema(const XsdSchema::Ptr &schema); private: - NamePool::Ptr m_namePool; + const NamePool::Ptr m_namePool; }; } diff --git a/src/xmlpatterns/schema/qxsdschemahelper.cpp b/src/xmlpatterns/schema/qxsdschemahelper.cpp index 752af89..ff169f7 100644 --- a/src/xmlpatterns/schema/qxsdschemahelper.cpp +++ b/src/xmlpatterns/schema/qxsdschemahelper.cpp @@ -409,7 +409,7 @@ bool XsdSchemaHelper::isValidlySubstitutable(const SchemaType::Ptr &type, const return false; } -bool XsdSchemaHelper::isSimpleDerivationOk(const SchemaType::Ptr &derivedType, const SchemaType::Ptr baseType, const SchemaType::DerivationConstraints &constraints) +bool XsdSchemaHelper::isSimpleDerivationOk(const SchemaType::Ptr &derivedType, const SchemaType::Ptr &baseType, const SchemaType::DerivationConstraints &constraints) { // @see http://www.w3.org/TR/xmlschema11-1/#cos-st-derived-ok @@ -453,7 +453,7 @@ bool XsdSchemaHelper::isSimpleDerivationOk(const SchemaType::Ptr &derivedType, c return false; } -bool XsdSchemaHelper::isComplexDerivationOk(const SchemaType::Ptr &derivedType, const SchemaType::Ptr baseType, const SchemaType::DerivationConstraints &constraints) +bool XsdSchemaHelper::isComplexDerivationOk(const SchemaType::Ptr &derivedType, const SchemaType::Ptr &baseType, const SchemaType::DerivationConstraints &constraints) { if (!derivedType) return false; diff --git a/src/xmlpatterns/schema/qxsdschemahelper_p.h b/src/xmlpatterns/schema/qxsdschemahelper_p.h index 1722b4c..918664e 100644 --- a/src/xmlpatterns/schema/qxsdschemahelper_p.h +++ b/src/xmlpatterns/schema/qxsdschemahelper_p.h @@ -55,12 +55,15 @@ namespace QPatternist /** * Checks whether the given @p nameSpace is allowed by the given namespace @p constraint. */ - static bool wildcardAllowsNamespaceName(const QString &nameSpace, const XsdWildcard::NamespaceConstraint::Ptr &constraint); + static bool wildcardAllowsNamespaceName(const QString &nameSpace, + const XsdWildcard::NamespaceConstraint::Ptr &constraint); /** * Checks whether the given @p name is allowed by the namespace constraint of the given @p wildcard. */ - static bool wildcardAllowsExpandedName(const QXmlName &name, const XsdWildcard::Ptr &wildcard, const NamePool::Ptr &namePool); + static bool wildcardAllowsExpandedName(const QXmlName &name, + const XsdWildcard::Ptr &wildcard, + const NamePool::Ptr &namePool); /** * Checks whether the @p wildcard is a subset of @p otherWildcard. @@ -75,25 +78,32 @@ namespace QPatternist /** * Returns the intersection of the given @p wildcard and @p otherWildcard. */ - static XsdWildcard::Ptr wildcardIntersection(const XsdWildcard::Ptr &wildcard, const XsdWildcard::Ptr &otherWildcard); + static XsdWildcard::Ptr wildcardIntersection(const XsdWildcard::Ptr &wildcard, + const XsdWildcard::Ptr &otherWildcard); /** * Returns whether the given @p type is validly substitutable for an @p otherType * under the given @p constraints. */ - static bool isValidlySubstitutable(const SchemaType::Ptr &type, const SchemaType::Ptr &otherType, const SchemaType::DerivationConstraints &constraints); + static bool isValidlySubstitutable(const SchemaType::Ptr &type, + const SchemaType::Ptr &otherType, + const SchemaType::DerivationConstraints &constraints); /** * Returns whether the simple @p derivedType can be derived from the simple @p baseType * under the given @p constraints. */ - static bool isSimpleDerivationOk(const SchemaType::Ptr &derivedType, const SchemaType::Ptr baseType, const SchemaType::DerivationConstraints &constraints); + static bool isSimpleDerivationOk(const SchemaType::Ptr &derivedType, + const SchemaType::Ptr &baseType, + const SchemaType::DerivationConstraints &constraints); /** * Returns whether the complex @p derivedType can be derived from the complex @p baseType * under the given @p constraints. */ - static bool isComplexDerivationOk(const SchemaType::Ptr &derivedType, const SchemaType::Ptr baseType, const SchemaType::DerivationConstraints &constraints); + static bool isComplexDerivationOk(const SchemaType::Ptr &derivedType, + const SchemaType::Ptr &baseType, + const SchemaType::DerivationConstraints &constraints); /** * This method takes the two string based operands @p operand1 and @p operand2 and converts them to instances of type @p type. @@ -111,41 +121,62 @@ namespace QPatternist * Returns whether the process content property of the @p derivedWildcard is valid * according to the process content property of its @p baseWildcard. */ - static bool checkWildcardProcessContents(const XsdWildcard::Ptr &baseWildcard, const XsdWildcard::Ptr &derivedWildcard); + static bool checkWildcardProcessContents(const XsdWildcard::Ptr &baseWildcard, + const XsdWildcard::Ptr &derivedWildcard); /** * Checks whether @[ member is a member of the substitution group with the given @p head. */ - static bool foundSubstitutionGroupTransitive(const XsdElement::Ptr &head, const XsdElement::Ptr &member, QSet &visitedElements); + static bool foundSubstitutionGroupTransitive(const XsdElement::Ptr &head, + const XsdElement::Ptr &member, + QSet &visitedElements); /** * A helper method that iterates over the type hierarchy from @p memberType up to @p headType and collects all * @p derivationSet and @p blockSet constraints that exists on the way there. */ - static void foundSubstitutionGroupTypeInheritance(const SchemaType::Ptr &headType, const SchemaType::Ptr &memberType, - QSet &derivationSet, NamedSchemaComponent::BlockingConstraints &blockSet); + static void foundSubstitutionGroupTypeInheritance(const SchemaType::Ptr &headType, + const SchemaType::Ptr &memberType, + QSet &derivationSet, + NamedSchemaComponent::BlockingConstraints &blockSet); /** * Checks if the @p member is transitive to @p head. */ - static bool substitutionGroupOkTransitive(const XsdElement::Ptr &head, const XsdElement::Ptr &member, const NamePool::Ptr &namePool); + static bool substitutionGroupOkTransitive(const XsdElement::Ptr &head, + const XsdElement::Ptr &member, + const NamePool::Ptr &namePool); /** * Checks if @p derivedAttributeGroup is a valid restriction for @p attributeGroup. */ - static bool isValidAttributeGroupRestriction(const XsdAttributeGroup::Ptr &derivedAttributeGroup, const XsdAttributeGroup::Ptr &attributeGroup, const XsdSchemaContext::Ptr &context, QString &errorMsg); + static bool isValidAttributeGroupRestriction(const XsdAttributeGroup::Ptr &derivedAttributeGroup, + const XsdAttributeGroup::Ptr &attributeGroup, + const XsdSchemaContext::Ptr &context, + QString &errorMsg); /** * Checks if @p derivedAttributeUses are a valid restriction for @p attributeUses. */ - static bool isValidAttributeUsesRestriction(const XsdAttributeUse::List &derivedAttributeUses, const XsdAttributeUse::List &attributeUses, - const XsdWildcard::Ptr &derivedWildcard, const XsdWildcard::Ptr &wildcard, const XsdSchemaContext::Ptr &context, QString &errorMsg); + static bool isValidAttributeUsesRestriction(const XsdAttributeUse::List &derivedAttributeUses, + const XsdAttributeUse::List &attributeUses, + const XsdWildcard::Ptr &derivedWildcard, + const XsdWildcard::Ptr &wildcard, + const XsdSchemaContext::Ptr &context, + QString &errorMsg); /** * Checks if @p derivedAttributeUses are a valid extension for @p attributeUses. */ - static bool isValidAttributeUsesExtension(const XsdAttributeUse::List &derivedAttributeUses, const XsdAttributeUse::List &attributeUses, - const XsdWildcard::Ptr &derivedWildcard, const XsdWildcard::Ptr &wildcard, const XsdSchemaContext::Ptr &context, QString &errorMsg); + static bool isValidAttributeUsesExtension(const XsdAttributeUse::List &derivedAttributeUses, + const XsdAttributeUse::List &attributeUses, + const XsdWildcard::Ptr &derivedWildcard, + const XsdWildcard::Ptr &wildcard, + const XsdSchemaContext::Ptr &context, + QString &errorMsg); + + private: + Q_DISABLE_COPY(XsdSchemaHelper) }; } diff --git a/src/xmlpatterns/schema/qxsdschemaparser.cpp b/src/xmlpatterns/schema/qxsdschemaparser.cpp index 9f1e75d..cabc12e 100644 --- a/src/xmlpatterns/schema/qxsdschemaparser.cpp +++ b/src/xmlpatterns/schema/qxsdschemaparser.cpp @@ -5,6 +5,7 @@ #include "qacceltreeresourceloader_p.h" #include "qautoptr_p.h" #include "qboolean_p.h" +#include "qcommonnamespaces_p.h" #include "qderivedinteger_p.h" #include "qderivedstring_p.h" #include "qqnamevalue_p.h" @@ -119,12 +120,28 @@ class TagValidationHandler void validate(XsdSchemaToken::NodeName token) { if (token == XsdSchemaToken::NoKeyword) { - m_parser->error(QtXmlPatterns::tr("can not process unknown element %1").arg(formatElement(m_parser->name().toString()))); + const QList tokens = m_machine.possibleTransitions(); + + QStringList elementNames; + for (int i = 0; i < tokens.count(); ++i) + elementNames.append(formatElement(XsdSchemaToken::toString(tokens.at(i)))); + + m_parser->error(QtXmlPatterns::tr("can not process unknown element %1, expected elements are: %2") + .arg(formatElement(m_parser->name().toString())) + .arg(elementNames.join(QLatin1String(", ")))); return; } if (!m_machine.proceed(token)) { - m_parser->error(QtXmlPatterns::tr("element %1 is not allowed in this scope").arg(formatElement(XsdSchemaToken::toString(token)))); + const QList tokens = m_machine.possibleTransitions(); + + QStringList elementNames; + for (int i = 0; i < tokens.count(); ++i) + elementNames.append(formatElement(XsdSchemaToken::toString(tokens.at(i)))); + + m_parser->error(QtXmlPatterns::tr("element %1 is not allowed in this scope, possible elements are: %2") + .arg(formatElement(XsdSchemaToken::toString(token))) + .arg(elementNames.join(QLatin1String(", ")))); return; } } @@ -132,7 +149,14 @@ class TagValidationHandler void finalize() const { if (!m_machine.inEndState()) { - m_parser->error(QtXmlPatterns::tr("child element is missing in that scope")); + const QList tokens = m_machine.possibleTransitions(); + + QStringList elementNames; + for (int i = 0; i < tokens.count(); ++i) + elementNames.append(formatElement(XsdSchemaToken::toString(tokens.at(i)))); + + m_parser->error(QtXmlPatterns::tr("child element is missing in that scope, possible child elements are: %1") + .arg(elementNames.join(QLatin1String(", ")))); } } @@ -425,8 +449,8 @@ void XsdSchemaParser::parseSchema(ParserType parserType) const QString version = readAttribute(QString::fromLatin1("version")); } - if (hasAttribute(QString::fromLatin1("http://www.w3.org/XML/1998/namespace"), QString::fromLatin1("lang"))) { - const QString value = readAttribute(QString::fromLatin1("lang"), QString::fromLatin1("http://www.w3.org/XML/1998/namespace")); + if (hasAttribute(CommonNamespaces::XML, QString::fromLatin1("lang"))) { + const QString value = readAttribute(QString::fromLatin1("lang"), CommonNamespaces::XML); const QRegExp exp(QString::fromLatin1("[a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*")); if (!exp.exactMatch(value)) { @@ -750,7 +774,7 @@ void XsdSchemaParser::parseRedefine() if (url.isRelative()) { Q_ASSERT(m_documentURI.isValid()); - url = m_documentURI.resolved(url); + url = m_documentURI.resolved(url); } // we parse the schema given in the redefine tag into its own context @@ -1176,8 +1200,8 @@ XsdDocumentation::Ptr XsdSchemaParser::parseDocumentation() } } - if (hasAttribute(QString::fromLatin1("http://www.w3.org/XML/1998/namespace"), QString::fromLatin1("lang"))) { - const QString value = readAttribute(QString::fromLatin1("lang"), QString::fromLatin1("http://www.w3.org/XML/1998/namespace")); + if (hasAttribute(CommonNamespaces::XML, QString::fromLatin1("lang"))) { + const QString value = readAttribute(QString::fromLatin1("lang"), CommonNamespaces::XML); const QRegExp exp(QString::fromLatin1("[a-zA-Z]{1,8}(-[a-zA-Z0-9]{1,8})*")); if (!exp.exactMatch(value)) { @@ -3948,7 +3972,7 @@ XsdAttribute::Ptr XsdSchemaParser::parseGlobalAttribute() error(QtXmlPatterns::tr("content of %1 attribute of %2 element must not be from namespace %3") .arg(formatAttribute("name")) .arg(formatElement("attribute")) - .arg(formatURI(QLatin1String("http://www.w3.org/2001/XMLSchema-instance")))); + .arg(formatURI(CommonNamespaces::XSI))); return attribute; } if (m_namePool->stringForLocalName(objectName.localName()) == QString::fromLatin1("xmlns")) { @@ -4170,7 +4194,7 @@ XsdAttributeUse::Ptr XsdSchemaParser::parseLocalAttribute(const NamedSchemaCompo error(QtXmlPatterns::tr("content of %1 attribute of %2 element must not be from namespace %3") .arg(formatAttribute("name")) .arg(formatElement("attribute")) - .arg(formatURI(QLatin1String("http://www.w3.org/2001/XMLSchema-instance")))); + .arg(formatURI(CommonNamespaces::XSI))); return attributeUse; } if (m_namePool->stringForLocalName(objectName.localName()) == QString::fromLatin1("xmlns")) { @@ -5858,7 +5882,7 @@ QString XsdSchemaParser::readXPathAttribute(const QString &attributeName, XPathT QXmlNamePool namePool(m_namePool.data()); - QXmlQuery::QueryLanguage language; + QXmlQuery::QueryLanguage language = QXmlQuery::XPath20; switch (type) { case XPath20: language = QXmlQuery::XPath20; break; case XPathSelector: language = QXmlQuery::XmlSchema11IdentityConstraintSelector; break; diff --git a/src/xmlpatterns/schema/qxsdstatemachine.cpp b/src/xmlpatterns/schema/qxsdstatemachine.cpp index e40e55b..4f36f22 100644 --- a/src/xmlpatterns/schema/qxsdstatemachine.cpp +++ b/src/xmlpatterns/schema/qxsdstatemachine.cpp @@ -114,6 +114,20 @@ bool XsdStateMachine::proceed(TransitionType transition) } template +QList XsdStateMachine::possibleTransitions() const +{ + // check that we are not in an invalid state + if (!m_transitions.contains(m_currentState)) { + return QList(); + } + + // fetch the transition entry for the current state + const QHash > &entry = m_transitions[m_currentState]; + + return entry.keys(); +} + +template template bool XsdStateMachine::proceed(InputType input) { @@ -259,7 +273,7 @@ typename XsdStateMachine::StateId XsdStateMachine it(nfaState); diff --git a/src/xmlpatterns/schema/qxsdstatemachine_p.h b/src/xmlpatterns/schema/qxsdstatemachine_p.h index 7988335..f0cf99d 100644 --- a/src/xmlpatterns/schema/qxsdstatemachine_p.h +++ b/src/xmlpatterns/schema/qxsdstatemachine_p.h @@ -113,6 +113,12 @@ namespace QPatternist bool proceed(TransitionType transition); /** + * Returns the list of transitions that are reachable from the current + * state. + */ + QList possibleTransitions() const; + + /** * Continues execution of the machine with the given @p input. * * @note To use this method, inputEqualsTransition must be implemented diff --git a/src/xmlpatterns/schema/qxsdvalidatedxmlnodemodel.cpp b/src/xmlpatterns/schema/qxsdvalidatedxmlnodemodel.cpp index 8e1645a..33bca4e 100644 --- a/src/xmlpatterns/schema/qxsdvalidatedxmlnodemodel.cpp +++ b/src/xmlpatterns/schema/qxsdvalidatedxmlnodemodel.cpp @@ -20,7 +20,7 @@ QT_BEGIN_NAMESPACE using namespace QPatternist; XsdValidatedXmlNodeModel::XsdValidatedXmlNodeModel(const QAbstractXmlNodeModel *model) - : m_internalModel(const_cast(model)) + : m_internalModel(model) { } diff --git a/src/xmlpatterns/schema/qxsdvalidatedxmlnodemodel_p.h b/src/xmlpatterns/schema/qxsdvalidatedxmlnodemodel_p.h index 579f41a..d52e369 100644 --- a/src/xmlpatterns/schema/qxsdvalidatedxmlnodemodel_p.h +++ b/src/xmlpatterns/schema/qxsdvalidatedxmlnodemodel_p.h @@ -134,11 +134,11 @@ namespace QPatternist virtual QVector attributes(const QXmlNodeModelIndex &element) const; private: - QAbstractXmlNodeModel::Ptr m_internalModel; - QHash m_assignedElements; - QHash m_assignedAttributes; - QHash m_assignedTypes; - QHash > m_idIdRefBindings; + QExplicitlySharedDataPointer m_internalModel; + QHash m_assignedElements; + QHash m_assignedAttributes; + QHash m_assignedTypes; + QHash > m_idIdRefBindings; }; } diff --git a/src/xmlpatterns/schema/qxsdvalidatinginstancereader.cpp b/src/xmlpatterns/schema/qxsdvalidatinginstancereader.cpp index 12fc477..8cb34d4 100644 --- a/src/xmlpatterns/schema/qxsdvalidatinginstancereader.cpp +++ b/src/xmlpatterns/schema/qxsdvalidatinginstancereader.cpp @@ -15,6 +15,7 @@ #include "qacceltreeresourceloader_p.h" #include "qbase64binary_p.h" #include "qboolean_p.h" +#include "qcommonnamespaces_p.h" #include "qderivedinteger_p.h" #include "qduration_p.h" #include "qgenericstaticcontext_p.h" @@ -64,14 +65,14 @@ namespace QPatternist } } -XsdValidatingInstanceReader::XsdValidatingInstanceReader(const XsdValidatedXmlNodeModel *model, const QUrl &documentUri, const XsdSchemaContext::Ptr &context) +XsdValidatingInstanceReader::XsdValidatingInstanceReader(XsdValidatedXmlNodeModel *model, const QUrl &documentUri, const XsdSchemaContext::Ptr &context) : XsdInstanceReader(model, context) - , m_model(const_cast(model)) + , m_model(model) , m_namePool(m_context->namePool()) - , m_xsiNilName(m_namePool->allocateQName(QLatin1String("http://www.w3.org/2001/XMLSchema-instance"), QLatin1String("nil"))) - , m_xsiTypeName(m_namePool->allocateQName(QLatin1String("http://www.w3.org/2001/XMLSchema-instance"), QLatin1String("type"))) - , m_xsiSchemaLocationName(m_namePool->allocateQName(QLatin1String("http://www.w3.org/2001/XMLSchema-instance"), QLatin1String("schemaLocation"))) - , m_xsiNoNamespaceSchemaLocationName(m_namePool->allocateQName(QLatin1String("http://www.w3.org/2001/XMLSchema-instance"), QLatin1String("noNamespaceSchemaLocation"))) + , m_xsiNilName(m_namePool->allocateQName(CommonNamespaces::XSI, QLatin1String("nil"))) + , m_xsiTypeName(m_namePool->allocateQName(CommonNamespaces::XSI, QLatin1String("type"))) + , m_xsiSchemaLocationName(m_namePool->allocateQName(CommonNamespaces::XSI, QLatin1String("schemaLocation"))) + , m_xsiNoNamespaceSchemaLocationName(m_namePool->allocateQName(CommonNamespaces::XSI, QLatin1String("noNamespaceSchemaLocation"))) , m_documentUri(documentUri) { m_idRefsType = m_context->schemaTypeFactory()->createSchemaType(m_namePool->allocateQName(CommonNamespaces::WXS, QLatin1String("IDREFS"))); @@ -152,7 +153,7 @@ bool XsdValidatingInstanceReader::read() void XsdValidatingInstanceReader::error(const QString &msg) const { - const_cast(m_context.data())->error(msg, XsdSchemaContext::XSDError, sourceLocation()); + m_context.data()->error(msg, XsdSchemaContext::XSDError, sourceLocation()); } bool XsdValidatingInstanceReader::loadSchema(const QString &targetNamespace, const QUrl &location) diff --git a/src/xmlpatterns/schema/qxsdvalidatinginstancereader_p.h b/src/xmlpatterns/schema/qxsdvalidatinginstancereader_p.h index 799ab44..28f3c3f 100644 --- a/src/xmlpatterns/schema/qxsdvalidatinginstancereader_p.h +++ b/src/xmlpatterns/schema/qxsdvalidatinginstancereader_p.h @@ -59,7 +59,7 @@ namespace QPatternist * @param documentUri The uri of the document the model is from. * @param context The context that is used to report errors etc. */ - XsdValidatingInstanceReader(const XsdValidatedXmlNodeModel *model, const QUrl &documentUri, const XsdSchemaContext::Ptr &context); + XsdValidatingInstanceReader(XsdValidatedXmlNodeModel *model, const QUrl &documentUri, const XsdSchemaContext::Ptr &context); /** * Adds a new @p schema to the pool of schemas that shall be used diff --git a/src/xmlpatterns/utils/qxpathhelper.cpp b/src/xmlpatterns/utils/qxpathhelper.cpp index 127e21f..5b32906 100644 --- a/src/xmlpatterns/utils/qxpathhelper.cpp +++ b/src/xmlpatterns/utils/qxpathhelper.cpp @@ -125,4 +125,16 @@ ItemType::Ptr XPathHelper::typeFromKind(const QXmlNodeModelIndex::NodeKind nodeK } } +QUrl XPathHelper::normalizeQueryURI(const QUrl &uri) +{ + Q_ASSERT_X(uri.isEmpty() || uri.isValid(), Q_FUNC_INFO, + "The URI passed to QXmlQuery::setQuery() must be valid or empty."); + if(uri.isEmpty()) + return QUrl::fromLocalFile(QCoreApplication::applicationFilePath()); + else if(uri.isRelative()) + return QUrl::fromLocalFile(QCoreApplication::applicationFilePath()).resolved(uri); + else + return uri; +} + QT_END_NAMESPACE diff --git a/src/xmlpatterns/utils/qxpathhelper_p.h b/src/xmlpatterns/utils/qxpathhelper_p.h index 7bf33e6..e36b8cb 100644 --- a/src/xmlpatterns/utils/qxpathhelper_p.h +++ b/src/xmlpatterns/utils/qxpathhelper_p.h @@ -128,6 +128,11 @@ namespace QPatternist static QPatternist::ItemTypePtr typeFromKind(const QXmlNodeModelIndex::NodeKind nodeKind); /** + * Normalizes an @p uri by resolving it to the application directory if empty. + */ + static QUrl normalizeQueryURI(const QUrl &uri); + + /** * @short Determines whether @p consists only of whitespace. Characters * considered whitespace are the ones for which QChar::isSpace() returns @c true for. * diff --git a/tests/auto/patternistheaders/tst_patternistheaders.cpp b/tests/auto/patternistheaders/tst_patternistheaders.cpp index ba7623e..3352a58 100644 --- a/tests/auto/patternistheaders/tst_patternistheaders.cpp +++ b/tests/auto/patternistheaders/tst_patternistheaders.cpp @@ -94,6 +94,10 @@ void tst_PatternistHeaders::run() const #include #include #include +#include +#include +#include +#include #include #include @@ -122,6 +126,10 @@ void tst_PatternistHeaders::run() const #include #include #include +#include +#include +#include +#include #include #include diff --git a/tests/auto/qxmlschema/tst_qxmlschema.cpp b/tests/auto/qxmlschema/tst_qxmlschema.cpp index 64012c1..7fc59bb 100644 --- a/tests/auto/qxmlschema/tst_qxmlschema.cpp +++ b/tests/auto/qxmlschema/tst_qxmlschema.cpp @@ -15,33 +15,8 @@ #include #include -class DummyMessageHandler : public QAbstractMessageHandler -{ - public: - DummyMessageHandler(QObject *parent = 0) - : QAbstractMessageHandler(parent) - { - } - - protected: - virtual void handleMessage(QtMsgType, const QString&, const QUrl&, const QSourceLocation&) - { - } -}; - -class DummyUriResolver : public QAbstractUriResolver -{ - public: - DummyUriResolver(QObject *parent = 0) - : QAbstractUriResolver(parent) - { - } - - virtual QUrl resolve(const QUrl&, const QUrl&) const - { - return QUrl(); - } -}; +#include "../qabstracturiresolver/TestURIResolver.h" +#include "../qxmlquery/MessageSilencer.h" /*! \class tst_QXmlSchema @@ -59,6 +34,17 @@ private Q_SLOTS: void defaultConstructor() const; void copyConstructor() const; void constructorQXmlNamePool() const; + void copyMutationTest() const; + + void isValid() const; + void documentUri() const; + + void loadSchemaUrlSuccess() const; + void loadSchemaUrlFail() const; + void loadSchemaDeviceSuccess() const; + void loadSchemaDeviceFail() const; + void loadSchemaDataSuccess() const; + void loadSchemaDataFail() const; void networkAccessManagerSignature() const; void networkAccessManagerDefaultValue() const; @@ -134,6 +120,150 @@ void tst_QXmlSchema::constructorQXmlNamePool() const QCOMPARE(name.prefix(np2), QString::fromLatin1("prefix")); } +void tst_QXmlSchema::copyMutationTest() const +{ + QXmlSchema schema1; + QXmlSchema schema2(schema1); + + // check that everything is equal + QVERIFY(schema2.messageHandler() == schema1.messageHandler()); + QVERIFY(schema2.uriResolver() == schema1.uriResolver()); + QVERIFY(schema2.networkAccessManager() == schema1.networkAccessManager()); + + MessageSilencer handler; + const TestURIResolver resolver; + QNetworkAccessManager manager; + + // modify schema1 + schema1.setMessageHandler(&handler); + schema1.setUriResolver(&resolver); + schema1.setNetworkAccessManager(&manager); + + // check that schema2 is not effected by the modifications of schema1 + QVERIFY(schema2.messageHandler() != schema1.messageHandler()); + QVERIFY(schema2.uriResolver() != schema1.uriResolver()); + QVERIFY(schema2.networkAccessManager() != schema1.networkAccessManager()); + + // modify schema1 further + const QByteArray data( "" + "" + "" ); + + const QUrl documentUri("http://www.qtsoftware.com/xmlschematest"); + schema1.load(data, documentUri); + + QVERIFY(schema2.isValid() != schema1.isValid()); +} + +void tst_QXmlSchema::isValid() const +{ + /* Check default value. */ + QXmlSchema schema; + QVERIFY(!schema.isValid()); +} + +void tst_QXmlSchema::documentUri() const +{ + const QByteArray data( "" + "" + "" ); + + const QUrl documentUri("http://www.qtsoftware.com/xmlschematest"); + QXmlSchema schema; + schema.load(data, documentUri); + + QCOMPARE(documentUri, schema.documentUri()); +} + +void tst_QXmlSchema::loadSchemaUrlSuccess() const +{ +/** + TODO: put valid schema file on given url and enable test + const QUrl url("http://notavailable/"); + + QXmlSchema schema; + QVERIFY(!schema.load(url)); +*/ +} + +void tst_QXmlSchema::loadSchemaUrlFail() const +{ + const QUrl url("http://notavailable/"); + + QXmlSchema schema; + QVERIFY(!schema.load(url)); +} + +void tst_QXmlSchema::loadSchemaDeviceSuccess() const +{ + QByteArray data( "" + "" + "" ); + + QBuffer buffer(&data); + buffer.open(QIODevice::ReadOnly); + + QXmlSchema schema; + QVERIFY(schema.load(&buffer)); +} + +void tst_QXmlSchema::loadSchemaDeviceFail() const +{ + QByteArray data( "" + "" + "" ); + + QBuffer buffer(&data); + // a closed device can not be loaded + + QXmlSchema schema; + QVERIFY(!schema.load(&buffer)); +} + +void tst_QXmlSchema::loadSchemaDataSuccess() const +{ + const QByteArray data( "" + "" + "" ); + QXmlSchema schema; + QVERIFY(schema.load(data)); +} + +void tst_QXmlSchema::loadSchemaDataFail() const +{ + // empty schema can not be loaded + const QByteArray data; + + QXmlSchema schema; + QVERIFY(!schema.load(data)); +} + + void tst_QXmlSchema::networkAccessManagerSignature() const { /* Const object. */ @@ -185,7 +315,7 @@ void tst_QXmlSchema::messageHandler() const { /* Test that we return the message handler that was set. */ { - DummyMessageHandler handler; + MessageSilencer handler; QXmlSchema schema; schema.setMessageHandler(&handler); @@ -200,6 +330,13 @@ void tst_QXmlSchema::uriResolverSignature() const /* The function should be const. */ schema.uriResolver(); + + /* Const object. */ + const TestURIResolver resolver; + + /* This should compile */ + QXmlSchema schema2; + schema2.setUriResolver(&resolver); } void tst_QXmlSchema::uriResolverDefaultValue() const @@ -215,7 +352,7 @@ void tst_QXmlSchema::uriResolver() const { /* Test that we return the uri resolver that was set. */ { - DummyUriResolver resolver; + TestURIResolver resolver; QXmlSchema schema; schema.setUriResolver(&resolver); diff --git a/tests/auto/qxmlschemavalidator/tst_qxmlschemavalidator.cpp b/tests/auto/qxmlschemavalidator/tst_qxmlschemavalidator.cpp index b021b08..3bbf506 100644 --- a/tests/auto/qxmlschemavalidator/tst_qxmlschemavalidator.cpp +++ b/tests/auto/qxmlschemavalidator/tst_qxmlschemavalidator.cpp @@ -16,33 +16,8 @@ #include #include -class DummyMessageHandler : public QAbstractMessageHandler -{ - public: - DummyMessageHandler(QObject *parent = 0) - : QAbstractMessageHandler(parent) - { - } - - protected: - virtual void handleMessage(QtMsgType, const QString&, const QUrl&, const QSourceLocation&) - { - } -}; - -class DummyUriResolver : public QAbstractUriResolver -{ - public: - DummyUriResolver(QObject *parent = 0) - : QAbstractUriResolver(parent) - { - } - - virtual QUrl resolve(const QUrl&, const QUrl&) const - { - return QUrl(); - } -}; +#include "../qabstracturiresolver/TestURIResolver.h" +#include "../qxmlquery/MessageSilencer.h" /*! \class tst_QXmlSchemaValidatorValidator @@ -60,6 +35,13 @@ private Q_SLOTS: void defaultConstructor() const; void propertyInitialization() const; + void loadInstanceUrlSuccess() const; + void loadInstanceUrlFail() const; + void loadInstanceDeviceSuccess() const; + void loadInstanceDeviceFail() const; + void loadInstanceDataSuccess() const; + void loadInstanceDataFail() const; + void networkAccessManagerSignature() const; void networkAccessManagerDefaultValue() const; void networkAccessManager() const; @@ -73,6 +55,26 @@ private Q_SLOTS: void uriResolver() const; }; +static QXmlSchema createValidSchema() +{ + const QByteArray data( "" + "" + " " + "" ); + + const QUrl documentUri("http://www.qtsoftware.com/xmlschematest"); + + QXmlSchema schema; + schema.load(data, documentUri); + + return schema; +} + void tst_QXmlSchemaValidator::defaultConstructor() const { /* Allocate instance in different orders. */ @@ -101,8 +103,8 @@ void tst_QXmlSchemaValidator::propertyInitialization() const { /* Verify that properties set in the schema are used as default values for the validator */ { - DummyMessageHandler handler; - DummyUriResolver resolver; + MessageSilencer handler; + TestURIResolver resolver; QNetworkAccessManager manager; QXmlSchema schema; @@ -117,6 +119,72 @@ void tst_QXmlSchemaValidator::propertyInitialization() const } } +void tst_QXmlSchemaValidator::loadInstanceUrlSuccess() const +{ +/* + TODO: put valid schema file on given url and enable test + const QXmlSchema schema(createValidSchema()); + const QUrl url("http://notavailable/"); + + QXmlSchemaValidator validator(schema); + QVERIFY(!validator.validate(url)); +*/ +} + +void tst_QXmlSchemaValidator::loadInstanceUrlFail() const +{ + const QXmlSchema schema(createValidSchema()); + const QUrl url("http://notavailable/"); + + QXmlSchemaValidator validator(schema); + QVERIFY(!validator.validate(url)); +} + +void tst_QXmlSchemaValidator::loadInstanceDeviceSuccess() const +{ + const QXmlSchema schema(createValidSchema()); + + QByteArray data( "Testme" ); + QBuffer buffer(&data); + buffer.open(QIODevice::ReadOnly); + + QXmlSchemaValidator validator(schema); + QVERIFY(validator.validate(&buffer)); +} + +void tst_QXmlSchemaValidator::loadInstanceDeviceFail() const +{ + const QXmlSchema schema(createValidSchema()); + + QByteArray data( "Testme" ); + QBuffer buffer(&data); + // a closed device can not be loaded + + QXmlSchemaValidator validator(schema); + QVERIFY(!validator.validate(&buffer)); +} + +void tst_QXmlSchemaValidator::loadInstanceDataSuccess() const +{ + const QXmlSchema schema(createValidSchema()); + + const QByteArray data( "Testme" ); + + QXmlSchemaValidator validator(schema); + QVERIFY(validator.validate(data)); +} + +void tst_QXmlSchemaValidator::loadInstanceDataFail() const +{ + const QXmlSchema schema(createValidSchema()); + + // empty instance can not be loaded + const QByteArray data; + + QXmlSchemaValidator validator(schema); + QVERIFY(!validator.validate(data)); +} + void tst_QXmlSchemaValidator::networkAccessManagerSignature() const { const QXmlSchema schema; @@ -202,7 +270,7 @@ void tst_QXmlSchemaValidator::messageHandlerDefaultValue() const { QXmlSchema schema; - DummyMessageHandler handler; + MessageSilencer handler; schema.setMessageHandler(&handler); const QXmlSchemaValidator validator(schema); @@ -214,7 +282,7 @@ void tst_QXmlSchemaValidator::messageHandler() const { /* Test that we return the message handler that was set. */ { - DummyMessageHandler handler; + MessageSilencer handler; const QXmlSchema schema; QXmlSchemaValidator validator(schema); @@ -225,7 +293,7 @@ void tst_QXmlSchemaValidator::messageHandler() const /* Test that we return the message handler that was set, even if the schema changed in between. */ { - DummyMessageHandler handler; + MessageSilencer handler; const QXmlSchema schema; QXmlSchemaValidator validator(schema); @@ -248,6 +316,13 @@ void tst_QXmlSchemaValidator::uriResolverSignature() const /* The function should be const. */ validator.uriResolver(); + + /* Const object. */ + const TestURIResolver resolver; + + /* This should compile */ + QXmlSchema schema2; + schema2.setUriResolver(&resolver); } void tst_QXmlSchemaValidator::uriResolverDefaultValue() const @@ -263,7 +338,7 @@ void tst_QXmlSchemaValidator::uriResolverDefaultValue() const { QXmlSchema schema; - DummyUriResolver resolver; + TestURIResolver resolver; schema.setUriResolver(&resolver); const QXmlSchemaValidator validator(schema); @@ -275,7 +350,7 @@ void tst_QXmlSchemaValidator::uriResolver() const { /* Test that we return the uri resolver that was set. */ { - DummyUriResolver resolver; + TestURIResolver resolver; const QXmlSchema schema; QXmlSchemaValidator validator(schema); @@ -286,7 +361,7 @@ void tst_QXmlSchemaValidator::uriResolver() const /* Test that we return the uri resolver that was set, even if the schema changed in between. */ { - DummyUriResolver resolver; + TestURIResolver resolver; const QXmlSchema schema; QXmlSchemaValidator validator(schema); diff --git a/tools/xmlpatternsvalidator/main.cpp b/tools/xmlpatternsvalidator/main.cpp index 032afc0..0ccbcfc 100644 --- a/tools/xmlpatternsvalidator/main.cpp +++ b/tools/xmlpatternsvalidator/main.cpp @@ -19,22 +19,29 @@ QT_USE_NAMESPACE -enum ExecutionMode -{ - InvalidMode, - SchemaOnlyMode, - SchemaAndInstanceMode, - InstanceOnlyMode -}; - int main(int argc, char **argv) { + enum ExitCode + { + Valid = 0, + Invalid, + ParseError + }; + + enum ExecutionMode + { + InvalidMode, + SchemaOnlyMode, + SchemaAndInstanceMode, + InstanceOnlyMode + }; + const QCoreApplication app(argc, argv); QCoreApplication::setApplicationName(QLatin1String("xmlpatternsvalidator")); if (argc != 2 && argc != 3) { qDebug() << QXmlPatternistCLI::tr("usage: xmlpatternsvalidator ( | | )"); - return 2; + return ParseError; } // parse command line arguments @@ -63,9 +70,9 @@ int main(int argc, char **argv) schema.load(QUrl(schemaUri)); if (schema.isValid()) - return 0; + return Valid; else - return 1; + return Invalid; } else if (mode == SchemaAndInstanceMode) { const QString instanceUri = QFile::decodeName(argv[1]); const QString schemaUri = QFile::decodeName(argv[2]); @@ -73,24 +80,24 @@ int main(int argc, char **argv) schema.load(QUrl(schemaUri)); if (!schema.isValid()) - return 1; + return Invalid; QXmlSchemaValidator validator(schema); if (validator.validate(QUrl(instanceUri))) - return 0; + return Valid; else - return 1; + return Invalid; } else if (mode == InstanceOnlyMode) { const QString instanceUri = QFile::decodeName(argv[1]); QXmlSchemaValidator validator(schema); if (validator.validate(QUrl(instanceUri))) - return 0; + return Valid; else - return 1; + return Invalid; } Q_ASSERT(false); - return 1; + return Invalid; } -- cgit v0.12 From 017fd8ebb129947603eeea5474a067d45a33eccb Mon Sep 17 00:00:00 2001 From: Tobias Koenig Date: Sat, 16 May 2009 20:45:26 +0200 Subject: Adapt license headers to LGPL --- examples/xmlpatterns/schema/main.cpp | 34 ++++++++++++++++++++-- examples/xmlpatterns/schema/mainwindow.cpp | 34 ++++++++++++++++++++-- examples/xmlpatterns/schema/mainwindow.h | 34 ++++++++++++++++++++-- src/xmlpatterns/api/qabstractxmlpullprovider.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/api/qabstractxmlpullprovider_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/api/qpullbridge.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/api/qpullbridge_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/api/qxmlschema.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/api/qxmlschema.h | 34 ++++++++++++++++++++-- src/xmlpatterns/api/qxmlschema_p.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/api/qxmlschema_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/api/qxmlschemavalidator.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/api/qxmlschemavalidator.h | 34 ++++++++++++++++++++-- src/xmlpatterns/api/qxmlschemavalidator_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/data/qcomparisonfactory.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/data/qcomparisonfactory_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/data/qvaluefactory.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/data/qvaluefactory_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/parser/qquerytransformparser_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qnamespacesupport.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qnamespacesupport_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdalternative.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdalternative_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdannotated.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdannotated_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdannotation.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdannotation_p.h | 34 ++++++++++++++++++++-- .../schema/qxsdapplicationinformation.cpp | 34 ++++++++++++++++++++-- .../schema/qxsdapplicationinformation_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdassertion.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdassertion_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdattribute.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdattribute_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdattributegroup.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdattributegroup_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdattributereference.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdattributereference_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdattributeterm.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdattributeterm_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdattributeuse.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdattributeuse_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdcomplextype.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdcomplextype_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsddocumentation.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsddocumentation_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdelement.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdelement_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdfacet.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdfacet_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdidcache.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdidcache_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdidchelper.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdidchelper_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdidentityconstraint.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdidentityconstraint_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdinstancereader.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdinstancereader_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdmodelgroup.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdmodelgroup_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdnotation.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdnotation_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdparticle.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdparticle_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdparticlechecker.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdparticlechecker_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdreference.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdreference_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdschema.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdschema_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdschemachecker.cpp | 34 ++++++++++++++++++++-- .../schema/qxsdschemachecker_helper.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdschemachecker_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdschemacontext.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdschemacontext_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdschemadebugger.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdschemadebugger_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdschemahelper.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdschemahelper_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdschemamerger.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdschemamerger_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdschemaparser_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdschemaparsercontext.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdschemaparsercontext_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdschemaresolver.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdschemaresolver_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdschematoken.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdschematoken_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdschematypesfactory.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdschematypesfactory_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdsimpletype.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdsimpletype_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdstatemachine.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdstatemachine_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdstatemachinebuilder.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdstatemachinebuilder_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdterm.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdterm_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdtypechecker.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdtypechecker_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsduserschematype.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsduserschematype_p.h | 34 ++++++++++++++++++++-- .../schema/qxsdvalidatedxmlnodemodel.cpp | 34 ++++++++++++++++++++-- .../schema/qxsdvalidatedxmlnodemodel_p.h | 34 ++++++++++++++++++++-- .../schema/qxsdvalidatinginstancereader.cpp | 34 ++++++++++++++++++++-- .../schema/qxsdvalidatinginstancereader_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdwildcard.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdwildcard_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdxpathexpression.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/qxsdxpathexpression_p.h | 34 ++++++++++++++++++++-- src/xmlpatterns/schema/tokens.xml | 34 ++++++++++++++++++++-- src/xmlpatterns/type/qnamedschemacomponent.cpp | 34 ++++++++++++++++++++-- src/xmlpatterns/type/qnamedschemacomponent_p.h | 34 ++++++++++++++++++++-- tools/xmlpatternsvalidator/main.cpp | 32 +++++++++++++++++++- tools/xmlpatternsvalidator/main.h | 32 +++++++++++++++++++- 114 files changed, 3646 insertions(+), 226 deletions(-) diff --git a/examples/xmlpatterns/schema/main.cpp b/examples/xmlpatterns/schema/main.cpp index 9537a87..50e1139 100644 --- a/examples/xmlpatterns/schema/main.cpp +++ b/examples/xmlpatterns/schema/main.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the examples of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/examples/xmlpatterns/schema/mainwindow.cpp b/examples/xmlpatterns/schema/mainwindow.cpp index 807a65b..6b43d7b 100644 --- a/examples/xmlpatterns/schema/mainwindow.cpp +++ b/examples/xmlpatterns/schema/mainwindow.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the examples of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/examples/xmlpatterns/schema/mainwindow.h b/examples/xmlpatterns/schema/mainwindow.h index e5dc2df..5f56afc 100644 --- a/examples/xmlpatterns/schema/mainwindow.h +++ b/examples/xmlpatterns/schema/mainwindow.h @@ -3,9 +3,39 @@ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the examples of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/api/qabstractxmlpullprovider.cpp b/src/xmlpatterns/api/qabstractxmlpullprovider.cpp index a80604b..7a7d87d 100644 --- a/src/xmlpatterns/api/qabstractxmlpullprovider.cpp +++ b/src/xmlpatterns/api/qabstractxmlpullprovider.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/api/qabstractxmlpullprovider_p.h b/src/xmlpatterns/api/qabstractxmlpullprovider_p.h index d05e649..99fb280 100644 --- a/src/xmlpatterns/api/qabstractxmlpullprovider_p.h +++ b/src/xmlpatterns/api/qabstractxmlpullprovider_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/api/qpullbridge.cpp b/src/xmlpatterns/api/qpullbridge.cpp index f347339..1456b32 100644 --- a/src/xmlpatterns/api/qpullbridge.cpp +++ b/src/xmlpatterns/api/qpullbridge.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/api/qpullbridge_p.h b/src/xmlpatterns/api/qpullbridge_p.h index 823d27b..14aa29a 100644 --- a/src/xmlpatterns/api/qpullbridge_p.h +++ b/src/xmlpatterns/api/qpullbridge_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/api/qxmlschema.cpp b/src/xmlpatterns/api/qxmlschema.cpp index 108212e..aa5b77c 100644 --- a/src/xmlpatterns/api/qxmlschema.cpp +++ b/src/xmlpatterns/api/qxmlschema.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/api/qxmlschema.h b/src/xmlpatterns/api/qxmlschema.h index cf56b1e..d057b2c 100644 --- a/src/xmlpatterns/api/qxmlschema.h +++ b/src/xmlpatterns/api/qxmlschema.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/api/qxmlschema_p.cpp b/src/xmlpatterns/api/qxmlschema_p.cpp index 21dc04a..7b96f82 100644 --- a/src/xmlpatterns/api/qxmlschema_p.cpp +++ b/src/xmlpatterns/api/qxmlschema_p.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/api/qxmlschema_p.h b/src/xmlpatterns/api/qxmlschema_p.h index efba256..b54d88f 100644 --- a/src/xmlpatterns/api/qxmlschema_p.h +++ b/src/xmlpatterns/api/qxmlschema_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/api/qxmlschemavalidator.cpp b/src/xmlpatterns/api/qxmlschemavalidator.cpp index fcde49c..7a4ce03 100644 --- a/src/xmlpatterns/api/qxmlschemavalidator.cpp +++ b/src/xmlpatterns/api/qxmlschemavalidator.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/api/qxmlschemavalidator.h b/src/xmlpatterns/api/qxmlschemavalidator.h index c82c522..e6683a5 100644 --- a/src/xmlpatterns/api/qxmlschemavalidator.h +++ b/src/xmlpatterns/api/qxmlschemavalidator.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/api/qxmlschemavalidator_p.h b/src/xmlpatterns/api/qxmlschemavalidator_p.h index 9910f6e..fbf7b1c 100644 --- a/src/xmlpatterns/api/qxmlschemavalidator_p.h +++ b/src/xmlpatterns/api/qxmlschemavalidator_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/data/qcomparisonfactory.cpp b/src/xmlpatterns/data/qcomparisonfactory.cpp index 7fe298b..79ff105 100644 --- a/src/xmlpatterns/data/qcomparisonfactory.cpp +++ b/src/xmlpatterns/data/qcomparisonfactory.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/data/qcomparisonfactory_p.h b/src/xmlpatterns/data/qcomparisonfactory_p.h index 09fc50b..88c587e 100644 --- a/src/xmlpatterns/data/qcomparisonfactory_p.h +++ b/src/xmlpatterns/data/qcomparisonfactory_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/data/qvaluefactory.cpp b/src/xmlpatterns/data/qvaluefactory.cpp index 04df29d..6c8fbec 100644 --- a/src/xmlpatterns/data/qvaluefactory.cpp +++ b/src/xmlpatterns/data/qvaluefactory.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/data/qvaluefactory_p.h b/src/xmlpatterns/data/qvaluefactory_p.h index 80b6207..0efe247 100644 --- a/src/xmlpatterns/data/qvaluefactory_p.h +++ b/src/xmlpatterns/data/qvaluefactory_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/parser/qquerytransformparser_p.h b/src/xmlpatterns/parser/qquerytransformparser_p.h index 759c39f..fb3ff72 100644 --- a/src/xmlpatterns/parser/qquerytransformparser_p.h +++ b/src/xmlpatterns/parser/qquerytransformparser_p.h @@ -54,9 +54,39 @@ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qnamespacesupport.cpp b/src/xmlpatterns/schema/qnamespacesupport.cpp index 349f451..dc76a6f 100644 --- a/src/xmlpatterns/schema/qnamespacesupport.cpp +++ b/src/xmlpatterns/schema/qnamespacesupport.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qnamespacesupport_p.h b/src/xmlpatterns/schema/qnamespacesupport_p.h index d338eae..1f8f955 100644 --- a/src/xmlpatterns/schema/qnamespacesupport_p.h +++ b/src/xmlpatterns/schema/qnamespacesupport_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdalternative.cpp b/src/xmlpatterns/schema/qxsdalternative.cpp index f3f589a..6e4a7ab 100644 --- a/src/xmlpatterns/schema/qxsdalternative.cpp +++ b/src/xmlpatterns/schema/qxsdalternative.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdalternative_p.h b/src/xmlpatterns/schema/qxsdalternative_p.h index 451441e..2b1c75d 100644 --- a/src/xmlpatterns/schema/qxsdalternative_p.h +++ b/src/xmlpatterns/schema/qxsdalternative_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdannotated.cpp b/src/xmlpatterns/schema/qxsdannotated.cpp index a29b5c4..6674180 100644 --- a/src/xmlpatterns/schema/qxsdannotated.cpp +++ b/src/xmlpatterns/schema/qxsdannotated.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdannotated_p.h b/src/xmlpatterns/schema/qxsdannotated_p.h index 251b252..18f0612 100644 --- a/src/xmlpatterns/schema/qxsdannotated_p.h +++ b/src/xmlpatterns/schema/qxsdannotated_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdannotation.cpp b/src/xmlpatterns/schema/qxsdannotation.cpp index 0a9dc04..37ec09f 100644 --- a/src/xmlpatterns/schema/qxsdannotation.cpp +++ b/src/xmlpatterns/schema/qxsdannotation.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdannotation_p.h b/src/xmlpatterns/schema/qxsdannotation_p.h index 8c23bae..1f2cd14 100644 --- a/src/xmlpatterns/schema/qxsdannotation_p.h +++ b/src/xmlpatterns/schema/qxsdannotation_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdapplicationinformation.cpp b/src/xmlpatterns/schema/qxsdapplicationinformation.cpp index 5669220..3b4da24 100644 --- a/src/xmlpatterns/schema/qxsdapplicationinformation.cpp +++ b/src/xmlpatterns/schema/qxsdapplicationinformation.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdapplicationinformation_p.h b/src/xmlpatterns/schema/qxsdapplicationinformation_p.h index 30839d3..224b511 100644 --- a/src/xmlpatterns/schema/qxsdapplicationinformation_p.h +++ b/src/xmlpatterns/schema/qxsdapplicationinformation_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdassertion.cpp b/src/xmlpatterns/schema/qxsdassertion.cpp index f6cbf81..5a97385 100644 --- a/src/xmlpatterns/schema/qxsdassertion.cpp +++ b/src/xmlpatterns/schema/qxsdassertion.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdassertion_p.h b/src/xmlpatterns/schema/qxsdassertion_p.h index 0ae5ff6..58f6073 100644 --- a/src/xmlpatterns/schema/qxsdassertion_p.h +++ b/src/xmlpatterns/schema/qxsdassertion_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdattribute.cpp b/src/xmlpatterns/schema/qxsdattribute.cpp index 6cf60ec..bf640e7 100644 --- a/src/xmlpatterns/schema/qxsdattribute.cpp +++ b/src/xmlpatterns/schema/qxsdattribute.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdattribute_p.h b/src/xmlpatterns/schema/qxsdattribute_p.h index 46d7355..e0ff854 100644 --- a/src/xmlpatterns/schema/qxsdattribute_p.h +++ b/src/xmlpatterns/schema/qxsdattribute_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdattributegroup.cpp b/src/xmlpatterns/schema/qxsdattributegroup.cpp index 8f2a47e..b6549eb 100644 --- a/src/xmlpatterns/schema/qxsdattributegroup.cpp +++ b/src/xmlpatterns/schema/qxsdattributegroup.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdattributegroup_p.h b/src/xmlpatterns/schema/qxsdattributegroup_p.h index 7a3bd79..4fe9c37 100644 --- a/src/xmlpatterns/schema/qxsdattributegroup_p.h +++ b/src/xmlpatterns/schema/qxsdattributegroup_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdattributereference.cpp b/src/xmlpatterns/schema/qxsdattributereference.cpp index 3c36a4e..6e5809c 100644 --- a/src/xmlpatterns/schema/qxsdattributereference.cpp +++ b/src/xmlpatterns/schema/qxsdattributereference.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdattributereference_p.h b/src/xmlpatterns/schema/qxsdattributereference_p.h index be48b3a..6500109 100644 --- a/src/xmlpatterns/schema/qxsdattributereference_p.h +++ b/src/xmlpatterns/schema/qxsdattributereference_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdattributeterm.cpp b/src/xmlpatterns/schema/qxsdattributeterm.cpp index a9c3898..6463e35 100644 --- a/src/xmlpatterns/schema/qxsdattributeterm.cpp +++ b/src/xmlpatterns/schema/qxsdattributeterm.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdattributeterm_p.h b/src/xmlpatterns/schema/qxsdattributeterm_p.h index 507df32..6e49cfc 100644 --- a/src/xmlpatterns/schema/qxsdattributeterm_p.h +++ b/src/xmlpatterns/schema/qxsdattributeterm_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdattributeuse.cpp b/src/xmlpatterns/schema/qxsdattributeuse.cpp index 96d81bc..0f7ed9f 100644 --- a/src/xmlpatterns/schema/qxsdattributeuse.cpp +++ b/src/xmlpatterns/schema/qxsdattributeuse.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdattributeuse_p.h b/src/xmlpatterns/schema/qxsdattributeuse_p.h index 86021e1..bf2eac5 100644 --- a/src/xmlpatterns/schema/qxsdattributeuse_p.h +++ b/src/xmlpatterns/schema/qxsdattributeuse_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdcomplextype.cpp b/src/xmlpatterns/schema/qxsdcomplextype.cpp index ddc9110..6f5a240 100644 --- a/src/xmlpatterns/schema/qxsdcomplextype.cpp +++ b/src/xmlpatterns/schema/qxsdcomplextype.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdcomplextype_p.h b/src/xmlpatterns/schema/qxsdcomplextype_p.h index 078c8f0..4333d24 100644 --- a/src/xmlpatterns/schema/qxsdcomplextype_p.h +++ b/src/xmlpatterns/schema/qxsdcomplextype_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsddocumentation.cpp b/src/xmlpatterns/schema/qxsddocumentation.cpp index 4994143..b2490f6 100644 --- a/src/xmlpatterns/schema/qxsddocumentation.cpp +++ b/src/xmlpatterns/schema/qxsddocumentation.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsddocumentation_p.h b/src/xmlpatterns/schema/qxsddocumentation_p.h index c44a2bb..35463da 100644 --- a/src/xmlpatterns/schema/qxsddocumentation_p.h +++ b/src/xmlpatterns/schema/qxsddocumentation_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdelement.cpp b/src/xmlpatterns/schema/qxsdelement.cpp index 2b8ccab..c344799 100644 --- a/src/xmlpatterns/schema/qxsdelement.cpp +++ b/src/xmlpatterns/schema/qxsdelement.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdelement_p.h b/src/xmlpatterns/schema/qxsdelement_p.h index e571687..70ecb7e 100644 --- a/src/xmlpatterns/schema/qxsdelement_p.h +++ b/src/xmlpatterns/schema/qxsdelement_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdfacet.cpp b/src/xmlpatterns/schema/qxsdfacet.cpp index 513eee8..b49d530 100644 --- a/src/xmlpatterns/schema/qxsdfacet.cpp +++ b/src/xmlpatterns/schema/qxsdfacet.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdfacet_p.h b/src/xmlpatterns/schema/qxsdfacet_p.h index f1f8110..fe845d0 100644 --- a/src/xmlpatterns/schema/qxsdfacet_p.h +++ b/src/xmlpatterns/schema/qxsdfacet_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdidcache.cpp b/src/xmlpatterns/schema/qxsdidcache.cpp index d4a7b64..2d4adc9 100644 --- a/src/xmlpatterns/schema/qxsdidcache.cpp +++ b/src/xmlpatterns/schema/qxsdidcache.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdidcache_p.h b/src/xmlpatterns/schema/qxsdidcache_p.h index b1d3c0f..c81e4dc 100644 --- a/src/xmlpatterns/schema/qxsdidcache_p.h +++ b/src/xmlpatterns/schema/qxsdidcache_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdidchelper.cpp b/src/xmlpatterns/schema/qxsdidchelper.cpp index 70980cb..0442f26 100644 --- a/src/xmlpatterns/schema/qxsdidchelper.cpp +++ b/src/xmlpatterns/schema/qxsdidchelper.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdidchelper_p.h b/src/xmlpatterns/schema/qxsdidchelper_p.h index 3034292..d25d713 100644 --- a/src/xmlpatterns/schema/qxsdidchelper_p.h +++ b/src/xmlpatterns/schema/qxsdidchelper_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdidentityconstraint.cpp b/src/xmlpatterns/schema/qxsdidentityconstraint.cpp index e72a005..eec1235 100644 --- a/src/xmlpatterns/schema/qxsdidentityconstraint.cpp +++ b/src/xmlpatterns/schema/qxsdidentityconstraint.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdidentityconstraint_p.h b/src/xmlpatterns/schema/qxsdidentityconstraint_p.h index 6870b1e..712ea98 100644 --- a/src/xmlpatterns/schema/qxsdidentityconstraint_p.h +++ b/src/xmlpatterns/schema/qxsdidentityconstraint_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdinstancereader.cpp b/src/xmlpatterns/schema/qxsdinstancereader.cpp index 81c40c9..9d2dc60 100644 --- a/src/xmlpatterns/schema/qxsdinstancereader.cpp +++ b/src/xmlpatterns/schema/qxsdinstancereader.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdinstancereader_p.h b/src/xmlpatterns/schema/qxsdinstancereader_p.h index 9df02d6..1896ad9 100644 --- a/src/xmlpatterns/schema/qxsdinstancereader_p.h +++ b/src/xmlpatterns/schema/qxsdinstancereader_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdmodelgroup.cpp b/src/xmlpatterns/schema/qxsdmodelgroup.cpp index 1245822..a791284 100644 --- a/src/xmlpatterns/schema/qxsdmodelgroup.cpp +++ b/src/xmlpatterns/schema/qxsdmodelgroup.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdmodelgroup_p.h b/src/xmlpatterns/schema/qxsdmodelgroup_p.h index b7b59ac..eae46b0 100644 --- a/src/xmlpatterns/schema/qxsdmodelgroup_p.h +++ b/src/xmlpatterns/schema/qxsdmodelgroup_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdnotation.cpp b/src/xmlpatterns/schema/qxsdnotation.cpp index cfa0cd3..6c1d7c0 100644 --- a/src/xmlpatterns/schema/qxsdnotation.cpp +++ b/src/xmlpatterns/schema/qxsdnotation.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdnotation_p.h b/src/xmlpatterns/schema/qxsdnotation_p.h index dc1d597..6af3f0c 100644 --- a/src/xmlpatterns/schema/qxsdnotation_p.h +++ b/src/xmlpatterns/schema/qxsdnotation_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdparticle.cpp b/src/xmlpatterns/schema/qxsdparticle.cpp index a2671fa..3e5be44 100644 --- a/src/xmlpatterns/schema/qxsdparticle.cpp +++ b/src/xmlpatterns/schema/qxsdparticle.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdparticle_p.h b/src/xmlpatterns/schema/qxsdparticle_p.h index 61e3eb3..491cb47 100644 --- a/src/xmlpatterns/schema/qxsdparticle_p.h +++ b/src/xmlpatterns/schema/qxsdparticle_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdparticlechecker.cpp b/src/xmlpatterns/schema/qxsdparticlechecker.cpp index 7a09f8a..fa26b8b 100644 --- a/src/xmlpatterns/schema/qxsdparticlechecker.cpp +++ b/src/xmlpatterns/schema/qxsdparticlechecker.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdparticlechecker_p.h b/src/xmlpatterns/schema/qxsdparticlechecker_p.h index 16a8d95..739eca0 100644 --- a/src/xmlpatterns/schema/qxsdparticlechecker_p.h +++ b/src/xmlpatterns/schema/qxsdparticlechecker_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdreference.cpp b/src/xmlpatterns/schema/qxsdreference.cpp index 0a934dd..e7fc409 100644 --- a/src/xmlpatterns/schema/qxsdreference.cpp +++ b/src/xmlpatterns/schema/qxsdreference.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdreference_p.h b/src/xmlpatterns/schema/qxsdreference_p.h index afcca25..d6a1693 100644 --- a/src/xmlpatterns/schema/qxsdreference_p.h +++ b/src/xmlpatterns/schema/qxsdreference_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdschema.cpp b/src/xmlpatterns/schema/qxsdschema.cpp index 260b06b..b9b9e99 100644 --- a/src/xmlpatterns/schema/qxsdschema.cpp +++ b/src/xmlpatterns/schema/qxsdschema.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdschema_p.h b/src/xmlpatterns/schema/qxsdschema_p.h index b41a2d5..9954f56 100644 --- a/src/xmlpatterns/schema/qxsdschema_p.h +++ b/src/xmlpatterns/schema/qxsdschema_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdschemachecker.cpp b/src/xmlpatterns/schema/qxsdschemachecker.cpp index 2a64327..42cfff6 100644 --- a/src/xmlpatterns/schema/qxsdschemachecker.cpp +++ b/src/xmlpatterns/schema/qxsdschemachecker.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdschemachecker_helper.cpp b/src/xmlpatterns/schema/qxsdschemachecker_helper.cpp index 98c4c63..850b17b 100644 --- a/src/xmlpatterns/schema/qxsdschemachecker_helper.cpp +++ b/src/xmlpatterns/schema/qxsdschemachecker_helper.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdschemachecker_p.h b/src/xmlpatterns/schema/qxsdschemachecker_p.h index 65fb87f..1ec85f9 100644 --- a/src/xmlpatterns/schema/qxsdschemachecker_p.h +++ b/src/xmlpatterns/schema/qxsdschemachecker_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdschemacontext.cpp b/src/xmlpatterns/schema/qxsdschemacontext.cpp index 65b2e52..4648864 100644 --- a/src/xmlpatterns/schema/qxsdschemacontext.cpp +++ b/src/xmlpatterns/schema/qxsdschemacontext.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdschemacontext_p.h b/src/xmlpatterns/schema/qxsdschemacontext_p.h index c3a9f15..3aad656 100644 --- a/src/xmlpatterns/schema/qxsdschemacontext_p.h +++ b/src/xmlpatterns/schema/qxsdschemacontext_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdschemadebugger.cpp b/src/xmlpatterns/schema/qxsdschemadebugger.cpp index 850192c..629333c 100644 --- a/src/xmlpatterns/schema/qxsdschemadebugger.cpp +++ b/src/xmlpatterns/schema/qxsdschemadebugger.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdschemadebugger_p.h b/src/xmlpatterns/schema/qxsdschemadebugger_p.h index 8966963..a88f432 100644 --- a/src/xmlpatterns/schema/qxsdschemadebugger_p.h +++ b/src/xmlpatterns/schema/qxsdschemadebugger_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdschemahelper.cpp b/src/xmlpatterns/schema/qxsdschemahelper.cpp index ff169f7..f31ebd6 100644 --- a/src/xmlpatterns/schema/qxsdschemahelper.cpp +++ b/src/xmlpatterns/schema/qxsdschemahelper.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdschemahelper_p.h b/src/xmlpatterns/schema/qxsdschemahelper_p.h index 918664e..1335691 100644 --- a/src/xmlpatterns/schema/qxsdschemahelper_p.h +++ b/src/xmlpatterns/schema/qxsdschemahelper_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdschemamerger.cpp b/src/xmlpatterns/schema/qxsdschemamerger.cpp index a924c9c..a0f22a2 100644 --- a/src/xmlpatterns/schema/qxsdschemamerger.cpp +++ b/src/xmlpatterns/schema/qxsdschemamerger.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdschemamerger_p.h b/src/xmlpatterns/schema/qxsdschemamerger_p.h index 54cc0f2..8154689 100644 --- a/src/xmlpatterns/schema/qxsdschemamerger_p.h +++ b/src/xmlpatterns/schema/qxsdschemamerger_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdschemaparser_p.h b/src/xmlpatterns/schema/qxsdschemaparser_p.h index 960fb86..c52702b 100644 --- a/src/xmlpatterns/schema/qxsdschemaparser_p.h +++ b/src/xmlpatterns/schema/qxsdschemaparser_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdschemaparsercontext.cpp b/src/xmlpatterns/schema/qxsdschemaparsercontext.cpp index 896619e..e4dc348 100644 --- a/src/xmlpatterns/schema/qxsdschemaparsercontext.cpp +++ b/src/xmlpatterns/schema/qxsdschemaparsercontext.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdschemaparsercontext_p.h b/src/xmlpatterns/schema/qxsdschemaparsercontext_p.h index 616aff3..f95f571 100644 --- a/src/xmlpatterns/schema/qxsdschemaparsercontext_p.h +++ b/src/xmlpatterns/schema/qxsdschemaparsercontext_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdschemaresolver.cpp b/src/xmlpatterns/schema/qxsdschemaresolver.cpp index 4c6910f..46d0c69 100644 --- a/src/xmlpatterns/schema/qxsdschemaresolver.cpp +++ b/src/xmlpatterns/schema/qxsdschemaresolver.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdschemaresolver_p.h b/src/xmlpatterns/schema/qxsdschemaresolver_p.h index 1222619..79d2a2d 100644 --- a/src/xmlpatterns/schema/qxsdschemaresolver_p.h +++ b/src/xmlpatterns/schema/qxsdschemaresolver_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdschematoken.cpp b/src/xmlpatterns/schema/qxsdschematoken.cpp index b527de6..e383b16 100644 --- a/src/xmlpatterns/schema/qxsdschematoken.cpp +++ b/src/xmlpatterns/schema/qxsdschematoken.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdschematoken_p.h b/src/xmlpatterns/schema/qxsdschematoken_p.h index 8cb1e76..58d1f4d 100644 --- a/src/xmlpatterns/schema/qxsdschematoken_p.h +++ b/src/xmlpatterns/schema/qxsdschematoken_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdschematypesfactory.cpp b/src/xmlpatterns/schema/qxsdschematypesfactory.cpp index 6cac0ff..b8f92a6 100644 --- a/src/xmlpatterns/schema/qxsdschematypesfactory.cpp +++ b/src/xmlpatterns/schema/qxsdschematypesfactory.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdschematypesfactory_p.h b/src/xmlpatterns/schema/qxsdschematypesfactory_p.h index 4fcd5fb..874a701 100644 --- a/src/xmlpatterns/schema/qxsdschematypesfactory_p.h +++ b/src/xmlpatterns/schema/qxsdschematypesfactory_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdsimpletype.cpp b/src/xmlpatterns/schema/qxsdsimpletype.cpp index 2e5b7f5..0365e5e 100644 --- a/src/xmlpatterns/schema/qxsdsimpletype.cpp +++ b/src/xmlpatterns/schema/qxsdsimpletype.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdsimpletype_p.h b/src/xmlpatterns/schema/qxsdsimpletype_p.h index 9ba34b6..d9f84c7 100644 --- a/src/xmlpatterns/schema/qxsdsimpletype_p.h +++ b/src/xmlpatterns/schema/qxsdsimpletype_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdstatemachine.cpp b/src/xmlpatterns/schema/qxsdstatemachine.cpp index 4f36f22..0672e1a 100644 --- a/src/xmlpatterns/schema/qxsdstatemachine.cpp +++ b/src/xmlpatterns/schema/qxsdstatemachine.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdstatemachine_p.h b/src/xmlpatterns/schema/qxsdstatemachine_p.h index f0cf99d..81fb853 100644 --- a/src/xmlpatterns/schema/qxsdstatemachine_p.h +++ b/src/xmlpatterns/schema/qxsdstatemachine_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdstatemachinebuilder.cpp b/src/xmlpatterns/schema/qxsdstatemachinebuilder.cpp index 866e010..a9e1d98 100644 --- a/src/xmlpatterns/schema/qxsdstatemachinebuilder.cpp +++ b/src/xmlpatterns/schema/qxsdstatemachinebuilder.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdstatemachinebuilder_p.h b/src/xmlpatterns/schema/qxsdstatemachinebuilder_p.h index 011153a..82eeea8 100644 --- a/src/xmlpatterns/schema/qxsdstatemachinebuilder_p.h +++ b/src/xmlpatterns/schema/qxsdstatemachinebuilder_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdterm.cpp b/src/xmlpatterns/schema/qxsdterm.cpp index 1dbe34b..92ea006 100644 --- a/src/xmlpatterns/schema/qxsdterm.cpp +++ b/src/xmlpatterns/schema/qxsdterm.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdterm_p.h b/src/xmlpatterns/schema/qxsdterm_p.h index f45d791..278b74d 100644 --- a/src/xmlpatterns/schema/qxsdterm_p.h +++ b/src/xmlpatterns/schema/qxsdterm_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdtypechecker.cpp b/src/xmlpatterns/schema/qxsdtypechecker.cpp index ab971a9..aabfcf6 100644 --- a/src/xmlpatterns/schema/qxsdtypechecker.cpp +++ b/src/xmlpatterns/schema/qxsdtypechecker.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdtypechecker_p.h b/src/xmlpatterns/schema/qxsdtypechecker_p.h index 2af20db..4b3f7c2 100644 --- a/src/xmlpatterns/schema/qxsdtypechecker_p.h +++ b/src/xmlpatterns/schema/qxsdtypechecker_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsduserschematype.cpp b/src/xmlpatterns/schema/qxsduserschematype.cpp index b8bf7e7..a985ba4 100644 --- a/src/xmlpatterns/schema/qxsduserschematype.cpp +++ b/src/xmlpatterns/schema/qxsduserschematype.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsduserschematype_p.h b/src/xmlpatterns/schema/qxsduserschematype_p.h index ab70f91..842fb00 100644 --- a/src/xmlpatterns/schema/qxsduserschematype_p.h +++ b/src/xmlpatterns/schema/qxsduserschematype_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdvalidatedxmlnodemodel.cpp b/src/xmlpatterns/schema/qxsdvalidatedxmlnodemodel.cpp index 33bca4e..e7a1503 100644 --- a/src/xmlpatterns/schema/qxsdvalidatedxmlnodemodel.cpp +++ b/src/xmlpatterns/schema/qxsdvalidatedxmlnodemodel.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdvalidatedxmlnodemodel_p.h b/src/xmlpatterns/schema/qxsdvalidatedxmlnodemodel_p.h index d52e369..77fc8f4 100644 --- a/src/xmlpatterns/schema/qxsdvalidatedxmlnodemodel_p.h +++ b/src/xmlpatterns/schema/qxsdvalidatedxmlnodemodel_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdvalidatinginstancereader.cpp b/src/xmlpatterns/schema/qxsdvalidatinginstancereader.cpp index 8cb34d4..1505152 100644 --- a/src/xmlpatterns/schema/qxsdvalidatinginstancereader.cpp +++ b/src/xmlpatterns/schema/qxsdvalidatinginstancereader.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdvalidatinginstancereader_p.h b/src/xmlpatterns/schema/qxsdvalidatinginstancereader_p.h index 28f3c3f..0402e99 100644 --- a/src/xmlpatterns/schema/qxsdvalidatinginstancereader_p.h +++ b/src/xmlpatterns/schema/qxsdvalidatinginstancereader_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdwildcard.cpp b/src/xmlpatterns/schema/qxsdwildcard.cpp index 6efb996..55eb4ba 100644 --- a/src/xmlpatterns/schema/qxsdwildcard.cpp +++ b/src/xmlpatterns/schema/qxsdwildcard.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdwildcard_p.h b/src/xmlpatterns/schema/qxsdwildcard_p.h index 8fbecb3..15fc159 100644 --- a/src/xmlpatterns/schema/qxsdwildcard_p.h +++ b/src/xmlpatterns/schema/qxsdwildcard_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdxpathexpression.cpp b/src/xmlpatterns/schema/qxsdxpathexpression.cpp index ba9d0a4..64bd687 100644 --- a/src/xmlpatterns/schema/qxsdxpathexpression.cpp +++ b/src/xmlpatterns/schema/qxsdxpathexpression.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/qxsdxpathexpression_p.h b/src/xmlpatterns/schema/qxsdxpathexpression_p.h index e57f7b7..e4f5427 100644 --- a/src/xmlpatterns/schema/qxsdxpathexpression_p.h +++ b/src/xmlpatterns/schema/qxsdxpathexpression_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/schema/tokens.xml b/src/xmlpatterns/schema/tokens.xml index 7ec9752..6736ad75 100644 --- a/src/xmlpatterns/schema/tokens.xml +++ b/src/xmlpatterns/schema/tokens.xml @@ -112,9 +112,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/type/qnamedschemacomponent.cpp b/src/xmlpatterns/type/qnamedschemacomponent.cpp index e45b9b6..71b7519 100644 --- a/src/xmlpatterns/type/qnamedschemacomponent.cpp +++ b/src/xmlpatterns/type/qnamedschemacomponent.cpp @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/src/xmlpatterns/type/qnamedschemacomponent_p.h b/src/xmlpatterns/type/qnamedschemacomponent_p.h index bc3121b..70da093 100644 --- a/src/xmlpatterns/type/qnamedschemacomponent_p.h +++ b/src/xmlpatterns/type/qnamedschemacomponent_p.h @@ -3,9 +3,39 @@ ** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtXmlPatterns of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/tools/xmlpatternsvalidator/main.cpp b/tools/xmlpatternsvalidator/main.cpp index 0ccbcfc..d53c783 100644 --- a/tools/xmlpatternsvalidator/main.cpp +++ b/tools/xmlpatternsvalidator/main.cpp @@ -5,7 +5,37 @@ ** ** This file is part of the Patternist project on Trolltech Labs. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/tools/xmlpatternsvalidator/main.h b/tools/xmlpatternsvalidator/main.h index 477a45a..85a4561 100644 --- a/tools/xmlpatternsvalidator/main.h +++ b/tools/xmlpatternsvalidator/main.h @@ -4,7 +4,37 @@ ** Contact: Qt Software Information (qt-info@nokia.com) ** ** This file is part of the Patternist project on Trolltech Labs. * ** - ** $TROLLTECH_DUAL_LICENSE$ + ** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -- cgit v0.12 From fa26e5759c645c9ed9c81a86dba72881dd1d776c Mon Sep 17 00:00:00 2001 From: Tobias Koenig Date: Tue, 19 May 2009 16:17:18 +0200 Subject: Add missing example files --- examples/xmlpatterns/schema/files/contact.xsd | 25 ++++++++++++++ .../xmlpatterns/schema/files/invalid_contact.xml | 11 ++++++ .../xmlpatterns/schema/files/invalid_order.xml | 13 +++++++ .../xmlpatterns/schema/files/invalid_recipe.xml | 14 ++++++++ examples/xmlpatterns/schema/files/order.xsd | 23 +++++++++++++ examples/xmlpatterns/schema/files/recipe.xsd | 40 ++++++++++++++++++++++ .../xmlpatterns/schema/files/valid_contact.xml | 11 ++++++ examples/xmlpatterns/schema/files/valid_order.xml | 18 ++++++++++ examples/xmlpatterns/schema/files/valid_recipe.xml | 13 +++++++ 9 files changed, 168 insertions(+) create mode 100644 examples/xmlpatterns/schema/files/contact.xsd create mode 100644 examples/xmlpatterns/schema/files/invalid_contact.xml create mode 100644 examples/xmlpatterns/schema/files/invalid_order.xml create mode 100644 examples/xmlpatterns/schema/files/invalid_recipe.xml create mode 100644 examples/xmlpatterns/schema/files/order.xsd create mode 100644 examples/xmlpatterns/schema/files/recipe.xsd create mode 100644 examples/xmlpatterns/schema/files/valid_contact.xml create mode 100644 examples/xmlpatterns/schema/files/valid_order.xml create mode 100644 examples/xmlpatterns/schema/files/valid_recipe.xml diff --git a/examples/xmlpatterns/schema/files/contact.xsd b/examples/xmlpatterns/schema/files/contact.xsd new file mode 100644 index 0000000..3e1b570 --- /dev/null +++ b/examples/xmlpatterns/schema/files/contact.xsd @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/xmlpatterns/schema/files/invalid_contact.xml b/examples/xmlpatterns/schema/files/invalid_contact.xml new file mode 100644 index 0000000..42f1edd --- /dev/null +++ b/examples/xmlpatterns/schema/files/invalid_contact.xml @@ -0,0 +1,11 @@ + + John + Doe + Prof. + + Sandakerveien 116 + N-0550 + Oslo + Norway + + diff --git a/examples/xmlpatterns/schema/files/invalid_order.xml b/examples/xmlpatterns/schema/files/invalid_order.xml new file mode 100644 index 0000000..8ffc5fd --- /dev/null +++ b/examples/xmlpatterns/schema/files/invalid_order.xml @@ -0,0 +1,13 @@ + + 234219 +
+ 21692 + 3 +
+
+ 24749 + 9 +
+ 2009-01-23 + yes +
diff --git a/examples/xmlpatterns/schema/files/invalid_recipe.xml b/examples/xmlpatterns/schema/files/invalid_recipe.xml new file mode 100644 index 0000000..4d75af6 --- /dev/null +++ b/examples/xmlpatterns/schema/files/invalid_recipe.xml @@ -0,0 +1,14 @@ + + Cheese on Toast + + + diff --git a/examples/xmlpatterns/schema/files/order.xsd b/examples/xmlpatterns/schema/files/order.xsd new file mode 100644 index 0000000..405cafe --- /dev/null +++ b/examples/xmlpatterns/schema/files/order.xsd @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/xmlpatterns/schema/files/recipe.xsd b/examples/xmlpatterns/schema/files/recipe.xsd new file mode 100644 index 0000000..bbbafd9 --- /dev/null +++ b/examples/xmlpatterns/schema/files/recipe.xsd @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/xmlpatterns/schema/files/valid_contact.xml b/examples/xmlpatterns/schema/files/valid_contact.xml new file mode 100644 index 0000000..53c04d4 --- /dev/null +++ b/examples/xmlpatterns/schema/files/valid_contact.xml @@ -0,0 +1,11 @@ + + John + Doe + 1977-12-25 + + Sandakerveien 116 + N-0550 + Oslo + Norway + + diff --git a/examples/xmlpatterns/schema/files/valid_order.xml b/examples/xmlpatterns/schema/files/valid_order.xml new file mode 100644 index 0000000..f83c36c --- /dev/null +++ b/examples/xmlpatterns/schema/files/valid_order.xml @@ -0,0 +1,18 @@ + + 194223 +
+ 22242 + 5 +
+
+ 32372 + 12 + without stripes +
+
+ 23649 + 2 +
+ 2009-01-23 + true +
diff --git a/examples/xmlpatterns/schema/files/valid_recipe.xml b/examples/xmlpatterns/schema/files/valid_recipe.xml new file mode 100644 index 0000000..f6499ba --- /dev/null +++ b/examples/xmlpatterns/schema/files/valid_recipe.xml @@ -0,0 +1,13 @@ + + Cheese on Toast + + + -- cgit v0.12 From adad01b142a0839a9c6e59275844f0c38924c25d Mon Sep 17 00:00:00 2001 From: Tobias Koenig Date: Tue, 19 May 2009 16:18:07 +0200 Subject: Remove unneeded qDebug statement --- src/xmlpatterns/schema/qxsdschemaparser.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/xmlpatterns/schema/qxsdschemaparser.cpp b/src/xmlpatterns/schema/qxsdschemaparser.cpp index cabc12e..3cd21af 100644 --- a/src/xmlpatterns/schema/qxsdschemaparser.cpp +++ b/src/xmlpatterns/schema/qxsdschemaparser.cpp @@ -251,7 +251,6 @@ void XsdSchemaParser::setTargetNamespaceExtended(const QString &targetNamespace) void XsdSchemaParser::setDocumentURI(const QUrl &uri) { - qDebug("%s", qPrintable(uri.toString())); m_documentURI = uri; // prevent to get included/imported/redefined twice -- cgit v0.12 From 317ab44d0c99fbc8b0a9f4136a107ad5d17e4539 Mon Sep 17 00:00:00 2001 From: Tobias Koenig Date: Tue, 19 May 2009 18:24:22 +0200 Subject: Extend auto tests for namepool checks --- tests/auto/qxmlschema/tst_qxmlschema.cpp | 4 ++ .../tst_qxmlschemavalidator.cpp | 62 ++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/tests/auto/qxmlschema/tst_qxmlschema.cpp b/tests/auto/qxmlschema/tst_qxmlschema.cpp index 7fc59bb..33978e8 100644 --- a/tests/auto/qxmlschema/tst_qxmlschema.cpp +++ b/tests/auto/qxmlschema/tst_qxmlschema.cpp @@ -118,6 +118,10 @@ void tst_QXmlSchema::constructorQXmlNamePool() const QCOMPARE(name.namespaceUri(np2), QString::fromLatin1("http://example.com/")); QCOMPARE(name.localName(np2), QString::fromLatin1("localName")); QCOMPARE(name.prefix(np2), QString::fromLatin1("prefix")); + + // make sure namePool() is const + const QXmlSchema constSchema; + np = constSchema.namePool(); } void tst_QXmlSchema::copyMutationTest() const diff --git a/tests/auto/qxmlschemavalidator/tst_qxmlschemavalidator.cpp b/tests/auto/qxmlschemavalidator/tst_qxmlschemavalidator.cpp index 3bbf506..0f15bc8 100644 --- a/tests/auto/qxmlschemavalidator/tst_qxmlschemavalidator.cpp +++ b/tests/auto/qxmlschemavalidator/tst_qxmlschemavalidator.cpp @@ -33,7 +33,9 @@ class tst_QXmlSchemaValidator : public QObject private Q_SLOTS: void defaultConstructor() const; + void constructorQXmlNamePool() const; void propertyInitialization() const; + void resetSchemaNamePool() const; void loadInstanceUrlSuccess() const; void loadInstanceUrlFail() const; @@ -119,6 +121,66 @@ void tst_QXmlSchemaValidator::propertyInitialization() const } } +void tst_QXmlSchemaValidator::constructorQXmlNamePool() const +{ + // test that the name pool from the schema is used by + // the schema validator as well + QXmlSchema schema; + + QXmlNamePool np = schema.namePool(); + + const QXmlName name(np, QLatin1String("localName"), + QLatin1String("http://example.com/"), + QLatin1String("prefix")); + + QXmlSchemaValidator validator(schema); + + QXmlNamePool np2(validator.namePool()); + QCOMPARE(name.namespaceUri(np2), QString::fromLatin1("http://example.com/")); + QCOMPARE(name.localName(np2), QString::fromLatin1("localName")); + QCOMPARE(name.prefix(np2), QString::fromLatin1("prefix")); + + // make sure namePool() is const + const QXmlSchemaValidator constValidator(schema); + np = constValidator.namePool(); +} + +void tst_QXmlSchemaValidator::resetSchemaNamePool() const +{ + QXmlSchema schema1; + QXmlNamePool np1 = schema1.namePool(); + + const QXmlName name1(np1, QLatin1String("localName"), + QLatin1String("http://example.com/"), + QLatin1String("prefix")); + + QXmlSchemaValidator validator(schema1); + + { + QXmlNamePool compNamePool(validator.namePool()); + QCOMPARE(name1.namespaceUri(compNamePool), QString::fromLatin1("http://example.com/")); + QCOMPARE(name1.localName(compNamePool), QString::fromLatin1("localName")); + QCOMPARE(name1.prefix(compNamePool), QString::fromLatin1("prefix")); + } + + QXmlSchema schema2; + QXmlNamePool np2 = schema2.namePool(); + + const QXmlName name2(np2, QLatin1String("remoteName"), + QLatin1String("http://trolltech.com/"), + QLatin1String("suffix")); + + // make sure that after re-setting the schema, the new namepool is used + validator.setSchema(schema2); + + { + QXmlNamePool compNamePool(validator.namePool()); + QCOMPARE(name2.namespaceUri(compNamePool), QString::fromLatin1("http://trolltech.com/")); + QCOMPARE(name2.localName(compNamePool), QString::fromLatin1("remoteName")); + QCOMPARE(name2.prefix(compNamePool), QString::fromLatin1("suffix")); + } +} + void tst_QXmlSchemaValidator::loadInstanceUrlSuccess() const { /* -- cgit v0.12 From ab5833178307fa9370868f61ff4cc7b18eb51fc0 Mon Sep 17 00:00:00 2001 From: Tobias Koenig Date: Tue, 19 May 2009 18:59:30 +0200 Subject: Forward errors from QXmlStreamReader to XsdSchemaParser (missed this commit on the first merge, autotest works again) --- src/xmlpatterns/schema/qxsdschemaparser.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/xmlpatterns/schema/qxsdschemaparser.cpp b/src/xmlpatterns/schema/qxsdschemaparser.cpp index 3cd21af..b74964d 100644 --- a/src/xmlpatterns/schema/qxsdschemaparser.cpp +++ b/src/xmlpatterns/schema/qxsdschemaparser.cpp @@ -290,6 +290,9 @@ bool XsdSchemaParser::parse(ParserType parserType) m_schemaResolver->addComponentLocationHash(m_componentLocationHash); m_schemaResolver->setDefaultOpenContent(m_defaultOpenContent, m_defaultOpenContentAppliesToEmpty); + if (QXmlStreamReader::error() != QXmlStreamReader::NoError) + error(errorString()); + return true; } -- cgit v0.12 From 9519f3ee67c8ab2de8d1ab5e584f8d3adb8875bd Mon Sep 17 00:00:00 2001 From: Tobias Koenig Date: Tue, 19 May 2009 20:04:10 +0200 Subject: Document xml schema enum in QRegExp --- src/corelib/tools/qregexp.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/corelib/tools/qregexp.cpp b/src/corelib/tools/qregexp.cpp index f69a99f..664dfc0 100644 --- a/src/corelib/tools/qregexp.cpp +++ b/src/corelib/tools/qregexp.cpp @@ -3700,6 +3700,9 @@ static void invalidateEngine(QRegExpPrivate *priv) equivalent to using the RegExp pattern on a string in which all metacharacters are escaped using escape(). + \value W3CXmlSchema11 The pattern is a regular expression as + defined by the W3C XML Schema 1.1 specification. + \sa setPatternSyntax() */ -- cgit v0.12 From f66a475a236649c94a47f668ba3461bdc325c308 Mon Sep 17 00:00:00 2001 From: Tobias Koenig Date: Tue, 19 May 2009 20:09:09 +0200 Subject: First version of documentation for schema example --- doc/src/examples.qdoc | 1 + doc/src/examples/schema.qdoc | 58 +++++++++++++++++++++++++++++ doc/src/images/schema-example.png | Bin 0 -> 84320 bytes examples/xmlpatterns/schema/mainwindow.cpp | 19 ++++++---- examples/xmlpatterns/schema/schema.ui | 2 +- src/xmlpatterns/api/qxmlschema.cpp | 10 +++++ 6 files changed, 81 insertions(+), 9 deletions(-) create mode 100644 doc/src/examples/schema.qdoc create mode 100644 doc/src/images/schema-example.png diff --git a/doc/src/examples.qdoc b/doc/src/examples.qdoc index 29c6c0b..a0e9b23 100644 --- a/doc/src/examples.qdoc +++ b/doc/src/examples.qdoc @@ -398,6 +398,7 @@ \o \l{xmlpatterns/qobjectxmlmodel}{QObject XML Model Example} \o \l{xmlpatterns/xquery/globalVariables}{C++ Source Code Analyzer Example} \o \l{xmlpatterns/trafficinfo}{Traffic Info}\raisedaster + \o \l{xmlpatterns/schema}{XML Schema Validation}\raisedaster \endlist \section1 Inter-Process Communication diff --git a/doc/src/examples/schema.qdoc b/doc/src/examples/schema.qdoc new file mode 100644 index 0000000..2287796 --- /dev/null +++ b/doc/src/examples/schema.qdoc @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example xmlpatterns/schema + \title XML Schema Validation Example + + This example shows how to use QtXmlPatterns to validate XML with + a W3C XML Schema. + + \section1 Introduction + + The example application shows different XML schema definitions and + for every definition two XML instance documents, one that is valid + according to the schema and one that is not. + The user can select the valid or invalid instance document, change + it and validate it again. + + \image schema-example.png +*/ diff --git a/doc/src/images/schema-example.png b/doc/src/images/schema-example.png new file mode 100644 index 0000000..5e95bf5 Binary files /dev/null and b/doc/src/images/schema-example.png differ diff --git a/examples/xmlpatterns/schema/mainwindow.cpp b/examples/xmlpatterns/schema/mainwindow.cpp index 6b43d7b..98276a3 100644 --- a/examples/xmlpatterns/schema/mainwindow.cpp +++ b/examples/xmlpatterns/schema/mainwindow.cpp @@ -69,7 +69,8 @@ class MessageHandler : public QAbstractMessageHandler } protected: - virtual void handleMessage(QtMsgType type, const QString &description, const QUrl &identifier, const QSourceLocation &sourceLocation) + virtual void handleMessage(QtMsgType type, const QString &description, + const QUrl &identifier, const QSourceLocation &sourceLocation) { Q_UNUSED(type); Q_UNUSED(identifier); @@ -127,7 +128,7 @@ void MainWindow::schemaSelected(int index) QFile schemaFile(QString(":/schema_%1.xsd").arg(index)); schemaFile.open(QIODevice::ReadOnly); - const QString schemaText(QString::fromLatin1(schemaFile.readAll())); + const QString schemaText(QString::fromUtf8(schemaFile.readAll())); schemaView->setPlainText(schemaText); validate(); @@ -137,7 +138,7 @@ void MainWindow::instanceSelected(int index) { QFile instanceFile(QString(":/instance_%1.xml").arg((2*schemaSelection->currentIndex()) + index)); instanceFile.open(QIODevice::ReadOnly); - const QString instanceText(QString::fromLatin1(instanceFile.readAll())); + const QString instanceText(QString::fromUtf8(instanceFile.readAll())); instanceEdit->setPlainText(instanceText); validate(); @@ -145,22 +146,22 @@ void MainWindow::instanceSelected(int index) void MainWindow::validate() { - const QByteArray schemaData = schemaView->toPlainText().toLatin1(); - const QByteArray instanceData = instanceEdit->toPlainText().toLatin1(); + const QByteArray schemaData = schemaView->toPlainText().toUtf8(); + const QByteArray instanceData = instanceEdit->toPlainText().toUtf8(); MessageHandler messageHandler; QXmlSchema schema; schema.setMessageHandler(&messageHandler); - schema.load(schemaData, QUrl("http://dummySchemaUrl/")); + schema.load(schemaData); bool errorOccurred = false; if (!schema.isValid()) { errorOccurred = true; } else { QXmlSchemaValidator validator(schema); - if (!validator.validate(instanceData, QUrl("http://dummyInstanceUrl"))) + if (!validator.validate(instanceData)) errorOccurred = true; } @@ -171,7 +172,9 @@ void MainWindow::validate() validationStatus->setText(tr("validation successful")); } - QString styleSheet = QString("QLabel {background: %1; padding: 3px}").arg(errorOccurred ? QColor(Qt::red).lighter(160).name() : QColor(Qt::green).lighter(160).name()); + const QString styleSheet = QString("QLabel {background: %1; padding: 3px}") + .arg(errorOccurred ? QColor(Qt::red).lighter(160).name() : + QColor(Qt::green).lighter(160).name()); validationStatus->setStyleSheet(styleSheet); } diff --git a/examples/xmlpatterns/schema/schema.ui b/examples/xmlpatterns/schema/schema.ui index af7020a..b67f444 100644 --- a/examples/xmlpatterns/schema/schema.ui +++ b/examples/xmlpatterns/schema/schema.ui @@ -11,7 +11,7 @@ - MainWindow + XML Schema Validation diff --git a/src/xmlpatterns/api/qxmlschema.cpp b/src/xmlpatterns/api/qxmlschema.cpp index aa5b77c..8e14f3f 100644 --- a/src/xmlpatterns/api/qxmlschema.cpp +++ b/src/xmlpatterns/api/qxmlschema.cpp @@ -88,6 +88,9 @@ QXmlSchema::~QXmlSchema() /*! Sets this QXmlSchema to a schema loaded from the \a source URI. + + If the schema \l {isValid()} {is invalid}, \c{false} is returned + and the behavior is undefined. */ bool QXmlSchema::load(const QUrl &source) { @@ -107,6 +110,10 @@ bool QXmlSchema::load(const QUrl &source) If \a source is \c null or not readable, or if \a documentUri is not a valid URI, behavior is undefined. + + If the schema \l {isValid()} {is invalid}, \c{false} is returned + and the behavior is undefined. + \sa isValid() */ bool QXmlSchema::load(QIODevice *source, const QUrl &documentUri) @@ -125,6 +132,9 @@ bool QXmlSchema::load(QIODevice *source, const QUrl &documentUri) If \a documentUri is not a valid URI, behavior is undefined. \sa isValid() + + If the schema \l {isValid()} {is invalid}, \c{false} is returned + and the behavior is undefined. */ bool QXmlSchema::load(const QByteArray &data, const QUrl &documentUri) { -- cgit v0.12 From 676d97d56a96c46cd9b9a2d6ba5d5f535f974d42 Mon Sep 17 00:00:00 2001 From: Tobias Koenig Date: Wed, 20 May 2009 21:11:14 +0200 Subject: Complete documentation of schema example and reference it from api docs --- doc/src/examples/schema.qdoc | 85 +++++++++++++++++++++++++++++ examples/xmlpatterns/schema/mainwindow.cpp | 10 ++++ src/xmlpatterns/api/qxmlschema.cpp | 2 + src/xmlpatterns/api/qxmlschemavalidator.cpp | 2 + 4 files changed, 99 insertions(+) diff --git a/doc/src/examples/schema.qdoc b/doc/src/examples/schema.qdoc index 2287796..80d158b 100644 --- a/doc/src/examples/schema.qdoc +++ b/doc/src/examples/schema.qdoc @@ -46,6 +46,8 @@ This example shows how to use QtXmlPatterns to validate XML with a W3C XML Schema. + \tableofcontents + \section1 Introduction The example application shows different XML schema definitions and @@ -54,5 +56,88 @@ The user can select the valid or invalid instance document, change it and validate it again. + \section2 The User Interface + + The UI for this example was created using \l{Qt Designer Manual} {Qt + Designer}: + \image schema-example.png + + The UI consists of three parts, at the top the XML schema \l{QComboBox} {selection} + and the schema \l{QTextBrowser} {viewer}, below the XML instance \l{QComboBox} {selection} + and the instance \l{QTextEdit} {editor} and at the bottom the validation status \l{QLabel} {label} + next to the validation \l{QPushButton} {button}. + + \section2 Validating XML Instance Documents + + You can select one of the three predefined XML schemas and for each schema + an valid or invalid instance document. A click on the 'Validate' button will + validate the content of the XML instance editor against the schema from the + XML schema viewer. As you can modify the content of the instance editor, different + instances can be tested and validation error messages analysed. + + \section1 Code Walk-Through + + The example's main() function creates the standard instance of + QApplication. Then it creates an instance of the mainwindow class, shows it, + and starts the Qt event loop: + + \snippet examples/xmlpatterns/schema/main.cpp 0 + + \section2 The UI Class: MainWindow + + The example's UI is a conventional Qt GUI application inheriting + QMainWindow and the class generated by \l{Qt Designer Manual} {Qt + Designer}: + + \snippet examples/xmlpatterns/schema/mainwindow.h 0 + + The constructor fills the schema and instance \l{QComboBox} selections with the predefined + schemas and instances and connects their \l{QComboBox::currentIndexChanged()} {currentIndexChanged()} + signals to the window's \c{schemaSelected()} resp. \c{instanceSelected()} slot. + Furthermore the signal-slot connections for the validation \l{QPushButton} {button} + and the instance \l{QTextEdit} {editor} are set up. + + The call to \c{schemaSelected(0)} and \c{instanceSelected(0)} will trigger the validation + of the initial Contact Schema example. + + \snippet examples/xmlpatterns/schema/mainwindow.cpp 0 + + In the \c{schemaSelected()} slot the content of the instance \l{QComboBox} {selection} + is adapted to the selected schema and the corresponding schema is loaded from the + \l{The Qt Resource System} {resource file} and displayed in the schema \l{QTextBrowser} {viewer}. + At the end of the method a revalidation is triggered. + + \snippet examples/xmlpatterns/schema/mainwindow.cpp 1 + + In the \c{instanceSelected()} slot the selected instance is loaded from the + \l{The Qt Resource System} {resource file} and loaded into the instance \l{QTextEdit} {editor} + an the revalidation is triggered again. + + \snippet examples/xmlpatterns/schema/mainwindow.cpp 2 + + The \c{validate()} slot does the actual work in this example. + At first it stores the content of the schema \l{QTextBrowser} {viewer} and the + \l{QTextEdit} {editor} into temporary \l{QByteArray} {variables}. + Then it instanciates a \c{MessageHandler} object which inherits from + \l{QAbstractMessageHandler} {QAbstractMessageHandler} and is a convenience + class to store error messages from the XmlPatterns system. + + \snippet examples/xmlpatterns/schema/mainwindow.cpp 4 + + After the \l{QXmlSchema} {QXmlSchema} is instanciated and the message handler set + on it, the \l{QXmlSchema::load()} {load()} method is called with the schema data as argument. + If the schema is invalid or a parsing error has occured, \l{QXmlSchema::isValid()} {isValid()} + returns \c{false} and the error is flagged in \c{errorOccurred}. + If the loading was successful, a \l{QXmlSchemaValidator} {QXmlSchemaValidator} is + instanciated and the schema passed in the constructor. + A call to \l{QXmlSchemaValidator::validate()} {validate()} will validate the passed + XML instance data against the XML schema. The return value of that method signals + whether the validation was successful. + Depending on the success the status \l{QLabel} {label} is set to 'validation successful' + or the error message stored in the \c{MessageHandler} + + The rest of the code does only some fancy coloring and eyecandy. + + \snippet examples/xmlpatterns/schema/mainwindow.cpp 3 */ diff --git a/examples/xmlpatterns/schema/mainwindow.cpp b/examples/xmlpatterns/schema/mainwindow.cpp index 98276a3..bee7407 100644 --- a/examples/xmlpatterns/schema/mainwindow.cpp +++ b/examples/xmlpatterns/schema/mainwindow.cpp @@ -45,6 +45,7 @@ #include "mainwindow.h" #include "xmlsyntaxhighlighter.h" +//! [4] class MessageHandler : public QAbstractMessageHandler { public: @@ -85,7 +86,9 @@ class MessageHandler : public QAbstractMessageHandler QString m_description; QSourceLocation m_sourceLocation; }; +//! [4] +//! [0] MainWindow::MainWindow() { setupUi(this); @@ -110,7 +113,9 @@ MainWindow::MainWindow() schemaSelected(0); instanceSelected(0); } +//! [0] +//! [1] void MainWindow::schemaSelected(int index) { instanceSelection->clear(); @@ -133,7 +138,9 @@ void MainWindow::schemaSelected(int index) validate(); } +//! [1] +//! [2] void MainWindow::instanceSelected(int index) { QFile instanceFile(QString(":/instance_%1.xml").arg((2*schemaSelection->currentIndex()) + index)); @@ -143,7 +150,9 @@ void MainWindow::instanceSelected(int index) validate(); } +//! [2] +//! [3] void MainWindow::validate() { const QByteArray schemaData = schemaView->toPlainText().toUtf8(); @@ -177,6 +186,7 @@ void MainWindow::validate() QColor(Qt::green).lighter(160).name()); validationStatus->setStyleSheet(styleSheet); } +//! [3] void MainWindow::textChanged() { diff --git a/src/xmlpatterns/api/qxmlschema.cpp b/src/xmlpatterns/api/qxmlschema.cpp index 8e14f3f..62b6a0e 100644 --- a/src/xmlpatterns/api/qxmlschema.cpp +++ b/src/xmlpatterns/api/qxmlschema.cpp @@ -57,6 +57,8 @@ The QXmlSchema class loads, compiles and validates W3C XML Schema files that can be used further for validation of XML instance documents via \l{QXmlSchemaValidator}. + + \sa QXmlSchemaValidator, {xmlpatterns/schema}{XML Schema Validation Example} */ /*! diff --git a/src/xmlpatterns/api/qxmlschemavalidator.cpp b/src/xmlpatterns/api/qxmlschemavalidator.cpp index 7a4ce03..a69b081 100644 --- a/src/xmlpatterns/api/qxmlschemavalidator.cpp +++ b/src/xmlpatterns/api/qxmlschemavalidator.cpp @@ -62,6 +62,8 @@ The QXmlSchemaValidator class loads, parses an XML instance document and validates it against a W3C XML Schema that has been compiled with \l{QXmlSchema}. + + \sa QXmlSchema, {xmlpatterns/schema}{XML Schema Validation Example} */ /*! -- cgit v0.12 From be0285b193d23fcf28ad84a73895ad15ece18e4c Mon Sep 17 00:00:00 2001 From: Tobias Koenig Date: Thu, 21 May 2009 12:25:00 +0200 Subject: Added code snippets for QXmlSchema and referenced them from api docs --- doc/src/snippets/qxmlschema/main.cpp | 118 +++++++++++++++++++++++++++++ doc/src/snippets/qxmlschema/qxmlschema.pro | 3 + doc/src/snippets/snippets.pro | 1 + src/xmlpatterns/api/qxmlschema.cpp | 16 ++++ 4 files changed, 138 insertions(+) create mode 100644 doc/src/snippets/qxmlschema/main.cpp create mode 100644 doc/src/snippets/qxmlschema/qxmlschema.pro diff --git a/doc/src/snippets/qxmlschema/main.cpp b/doc/src/snippets/qxmlschema/main.cpp new file mode 100644 index 0000000..9e72f40 --- /dev/null +++ b/doc/src/snippets/qxmlschema/main.cpp @@ -0,0 +1,118 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +class Schema +{ + public: + void loadFromUrl() const; + void loadFromFile() const; + void loadFromData() const; +}; + +void Schema::loadFromUrl() const +{ +//! [0] + QUrl url("http://www.schema-example.org/myschema.xsd"); + + QXmlSchema schema; + if (schema.load(url) == true) + qDebug() << "schema is valid"; + else + qDebug() << "schema is invalid"; +//! [0] +} + +void Schema::loadFromFile() const +{ +//! [1] + QFile file("myschema.xsd"); + file.open(QIODevice::ReadOnly); + + QXmlSchema schema; + schema.load(&file, QUrl::fromLocalFile(file.fileName())); + + if (schema.isValid()) + qDebug() << "schema is valid"; + else + qDebug() << "schema is invalid"; +//! [1] +} + +void Schema::loadFromData() const +{ +//! [2] + QByteArray data( "" + "" + "" ); + + QBuffer buffer(&data); + buffer.open(QIODevice::ReadOnly); + + QXmlSchema schema; + schema.load(&buffer); + + if (schema.isValid()) + qDebug() << "schema is valid"; + else + qDebug() << "schema is invalid"; +//! [2] +} + +int main(int argc, char **argv) +{ + QCoreApplication app(argc, argv); + + Schema schema; + + schema.loadFromUrl(); + schema.loadFromFile(); + schema.loadFromData(); + + return 0; +} diff --git a/doc/src/snippets/qxmlschema/qxmlschema.pro b/doc/src/snippets/qxmlschema/qxmlschema.pro new file mode 100644 index 0000000..7e8782a --- /dev/null +++ b/doc/src/snippets/qxmlschema/qxmlschema.pro @@ -0,0 +1,3 @@ +SOURCES += main.cpp + +QT += xmlpatterns diff --git a/doc/src/snippets/snippets.pro b/doc/src/snippets/snippets.pro index 50e33b3..e7219a6 100644 --- a/doc/src/snippets/snippets.pro +++ b/doc/src/snippets/snippets.pro @@ -73,6 +73,7 @@ SUBDIRS = brush \ quiloader \ qx11embedcontainer \ qx11embedwidget \ + qxmlschema \ reading-selections \ scribe-overview \ separations \ diff --git a/src/xmlpatterns/api/qxmlschema.cpp b/src/xmlpatterns/api/qxmlschema.cpp index 62b6a0e..ec370ca 100644 --- a/src/xmlpatterns/api/qxmlschema.cpp +++ b/src/xmlpatterns/api/qxmlschema.cpp @@ -93,6 +93,12 @@ QXmlSchema::~QXmlSchema() If the schema \l {isValid()} {is invalid}, \c{false} is returned and the behavior is undefined. + + Example: + + \snippet doc/src/snippets/qxmlschema/main.cpp 0 + + \sa isValid() */ bool QXmlSchema::load(const QUrl &source) { @@ -116,6 +122,10 @@ bool QXmlSchema::load(const QUrl &source) If the schema \l {isValid()} {is invalid}, \c{false} is returned and the behavior is undefined. + Example: + + \snippet doc/src/snippets/qxmlschema/main.cpp 1 + \sa isValid() */ bool QXmlSchema::load(QIODevice *source, const QUrl &documentUri) @@ -137,6 +147,12 @@ bool QXmlSchema::load(QIODevice *source, const QUrl &documentUri) If the schema \l {isValid()} {is invalid}, \c{false} is returned and the behavior is undefined. + + Example: + + \snippet doc/src/snippets/qxmlschema/main.cpp 2 + + \sa isValid() */ bool QXmlSchema::load(const QByteArray &data, const QUrl &documentUri) { -- cgit v0.12 From b24611f14453e6b870e25bdc3edcd4f6447ae87e Mon Sep 17 00:00:00 2001 From: Tobias Koenig Date: Thu, 21 May 2009 15:16:40 +0200 Subject: Added code snippets for QXmlSchemaValidator and referenced them from api docs --- doc/src/snippets/qxmlschemavalidator/main.cpp | 137 +++++++++++++++++++++ .../qxmlschemavalidator/qxmlschemavalidator.pro | 3 + doc/src/snippets/snippets.pro | 1 + src/xmlpatterns/api/qxmlschemavalidator.cpp | 12 ++ 4 files changed, 153 insertions(+) create mode 100644 doc/src/snippets/qxmlschemavalidator/main.cpp create mode 100644 doc/src/snippets/qxmlschemavalidator/qxmlschemavalidator.pro diff --git a/doc/src/snippets/qxmlschemavalidator/main.cpp b/doc/src/snippets/qxmlschemavalidator/main.cpp new file mode 100644 index 0000000..13cd45f --- /dev/null +++ b/doc/src/snippets/qxmlschemavalidator/main.cpp @@ -0,0 +1,137 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +class SchemaValidator +{ + public: + void validateFromUrl() const; + void validateFromFile() const; + void validateFromData() const; + + private: + QXmlSchema getSchema() const; +}; + +void SchemaValidator::validateFromUrl() const +{ +//! [0] + const QXmlSchema schema = getSchema(); + + const QUrl url("http://www.schema-example.org/test.xml"); + + QXmlSchemaValidator validator(schema); + if (validator.validate(url)) + qDebug() << "instance document is valid"; + else + qDebug() << "instance document is invalid"; +//! [0] +} + +void SchemaValidator::validateFromFile() const +{ +//! [1] + const QXmlSchema schema = getSchema(); + + QFile file("test.xml"); + file.open(QIODevice::ReadOnly); + + QXmlSchemaValidator validator(schema); + if (validator.validate(&file, QUrl::fromLocalFile(file.fileName()))) + qDebug() << "instance document is valid"; + else + qDebug() << "instance document is invalid"; +//! [1] +} + +void SchemaValidator::validateFromData() const +{ +//! [2] + const QXmlSchema schema = getSchema(); + + QByteArray data("" + ""); + + QBuffer buffer(&data); + buffer.open(QIODevice::ReadOnly); + + QXmlSchemaValidator validator(schema); + if (validator.validate(&buffer)) + qDebug() << "instance document is valid"; + else + qDebug() << "instance document is invalid"; +//! [2] +} + +QXmlSchema SchemaValidator::getSchema() const +{ + QByteArray data("" + "" + ""); + + QBuffer buffer(&data); + buffer.open(QIODevice::ReadOnly); + + QXmlSchema schema; + schema.load(&buffer); + + return schema; +} + +int main(int argc, char **argv) +{ + QCoreApplication app(argc, argv); + + SchemaValidator validator; + + validator.validateFromUrl(); + validator.validateFromFile(); + validator.validateFromData(); + + return 0; +} diff --git a/doc/src/snippets/qxmlschemavalidator/qxmlschemavalidator.pro b/doc/src/snippets/qxmlschemavalidator/qxmlschemavalidator.pro new file mode 100644 index 0000000..7e8782a --- /dev/null +++ b/doc/src/snippets/qxmlschemavalidator/qxmlschemavalidator.pro @@ -0,0 +1,3 @@ +SOURCES += main.cpp + +QT += xmlpatterns diff --git a/doc/src/snippets/snippets.pro b/doc/src/snippets/snippets.pro index e7219a6..e3e7eca 100644 --- a/doc/src/snippets/snippets.pro +++ b/doc/src/snippets/snippets.pro @@ -74,6 +74,7 @@ SUBDIRS = brush \ qx11embedcontainer \ qx11embedwidget \ qxmlschema \ + qxmlschemavalidator \ reading-selections \ scribe-overview \ separations \ diff --git a/src/xmlpatterns/api/qxmlschemavalidator.cpp b/src/xmlpatterns/api/qxmlschemavalidator.cpp index a69b081..b72b1ef 100644 --- a/src/xmlpatterns/api/qxmlschemavalidator.cpp +++ b/src/xmlpatterns/api/qxmlschemavalidator.cpp @@ -106,6 +106,10 @@ void QXmlSchemaValidator::setSchema(const QXmlSchema &schema) Returns \c true if the XML instance document is valid according the schema, \c false otherwise. + + Example: + + \snippet doc/src/snippets/qxmlschemavalidator/main.cpp 2 */ bool QXmlSchemaValidator::validate(const QByteArray &data, const QUrl &documentUri) const { @@ -122,6 +126,10 @@ bool QXmlSchemaValidator::validate(const QByteArray &data, const QUrl &documentU Returns \c true if the XML instance document is valid according the schema, \c false otherwise. + + Example: + + \snippet doc/src/snippets/qxmlschemavalidator/main.cpp 0 */ bool QXmlSchemaValidator::validate(const QUrl &source) const { @@ -143,6 +151,10 @@ bool QXmlSchemaValidator::validate(const QUrl &source) const Returns \c true if the XML instance document is valid according the schema, \c false otherwise. + + Example: + + \snippet doc/src/snippets/qxmlschemavalidator/main.cpp 1 */ bool QXmlSchemaValidator::validate(QIODevice *source, const QUrl &documentUri) const { -- cgit v0.12 From 9281f4c219cec2e6a1e24b43e1edd0feb0fcfce5 Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Fri, 29 May 2009 14:45:35 +0200 Subject: First bunch of changes after an very first API review This basically move some logic from the scene to the index base class. Lot of work need to be done in order to benefits from the device transform. The sorting needs to be move in the BSP tree. --- src/gui/graphicsview/graphicsview.pri | 1 + src/gui/graphicsview/qgraphicsitem.cpp | 17 +- src/gui/graphicsview/qgraphicsitem.h | 4 + src/gui/graphicsview/qgraphicsscene.cpp | 618 +++------------------ src/gui/graphicsview/qgraphicsscene.h | 9 + src/gui/graphicsview/qgraphicsscene_bsp.cpp | 12 +- src/gui/graphicsview/qgraphicsscene_bsp_p.h | 8 +- src/gui/graphicsview/qgraphicsscene_p.h | 88 ++- .../graphicsview/qgraphicsscenebsptreeindex_p.cpp | 120 ++-- .../graphicsview/qgraphicsscenebsptreeindex_p.h | 18 +- src/gui/graphicsview/qgraphicssceneindex.cpp | 558 +++++++++++++++++-- src/gui/graphicsview/qgraphicssceneindex.h | 50 +- src/gui/graphicsview/qgraphicssceneindex_p.h | 96 ++++ src/gui/graphicsview/qgraphicsscenelinearindex_p.h | 17 +- src/gui/graphicsview/qgraphicsview.cpp | 21 +- 15 files changed, 857 insertions(+), 780 deletions(-) create mode 100644 src/gui/graphicsview/qgraphicssceneindex_p.h diff --git a/src/gui/graphicsview/graphicsview.pri b/src/gui/graphicsview/graphicsview.pri index 9097497..cc57892 100644 --- a/src/gui/graphicsview/graphicsview.pri +++ b/src/gui/graphicsview/graphicsview.pri @@ -10,6 +10,7 @@ HEADERS += \ graphicsview/qgraphicsscene_bsp_p.h \ graphicsview/qgraphicsscenelinearindex_p.h \ graphicsview/qgraphicssceneindex.h \ + graphicsview/qgraphicssceneindex_p.h \ graphicsview/qgraphicssceneevent.h \ graphicsview/qgraphicsview_p.h \ graphicsview/qgraphicsview.h diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index c1d44d3..fc5895c 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -567,17 +567,6 @@ QT_BEGIN_NAMESPACE -// QRectF::intersects() returns false always if either the source or target -// rectangle's width or height are 0. This works around that problem. -static inline void _q_adjustRect(QRectF *rect) -{ - Q_ASSERT(rect); - if (!rect->width()) - rect->adjust(-0.00001, 0, 0.00001, 0); - if (!rect->height()) - rect->adjust(0, -0.00001, 0, 0.00001); -} - static inline void _q_adjustRect(QRect *rect) { Q_ASSERT(rect); @@ -6357,7 +6346,7 @@ void QGraphicsItem::addToIndex() return; } if (d_ptr->scene) - d_ptr->scene->d_func()->index->insertItem(this); + d_ptr->scene->d_func()->index->addItem(this); d_ptr->updateHelper(); } @@ -6372,7 +6361,7 @@ void QGraphicsItem::removeFromIndex() { d_ptr->updateHelper(); if (d_ptr->scene) - d_ptr->scene->d_func()->index->removeItem(this,false); + d_ptr->scene->d_func()->index->removeItem(this); } /*! @@ -6393,7 +6382,7 @@ void QGraphicsItem::prepareGeometryChange() if (d_ptr->scene) { d_ptr->updateHelper(QRectF(), false, /*maybeDirtyClipPath=*/!d_ptr->inSetPosHelper); QGraphicsScenePrivate *scenePrivate = d_ptr->scene->d_func(); - scenePrivate->index->updateItem(this); + scenePrivate->index->prepareBoundingRectChange(this); } if (d_ptr->inSetPosHelper) diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index cb86020..e244c13 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -409,6 +409,8 @@ protected: virtual void setExtension(Extension extension, const QVariant &variant); virtual QVariant extension(const QVariant &variant) const; + bool operator<(const QGraphicsItem *other) const; + protected: QGraphicsItem(QGraphicsItemPrivate &dd, QGraphicsItem *parent, QGraphicsScene *scene); @@ -430,6 +432,8 @@ private: friend class QGraphicsWidget; friend class QGraphicsWidgetPrivate; friend class QGraphicsProxyWidgetPrivate; + friend class QGraphicsSceneIndex; + friend class QGraphicsSceneIndexPrivate; friend class QGraphicsSceneBspTreeIndex; friend class ::tst_QGraphicsItem; friend bool qt_closestLeaf(const QGraphicsItem *, const QGraphicsItem *); diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 51c8294..9b6d40b 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -249,65 +249,6 @@ QT_BEGIN_NAMESPACE -static inline bool QRectF_intersects(const QRectF &s, const QRectF &r) -{ - qreal xp = s.left(); - qreal yp = s.top(); - qreal w = s.width(); - qreal h = s.height(); - qreal l1 = xp; - qreal r1 = xp; - if (w < 0) - l1 += w; - else - r1 += w; - - qreal l2 = r.left(); - qreal r2 = r.left(); - if (w < 0) - l2 += r.width(); - else - r2 += r.width(); - - if (l1 >= r2 || l2 >= r1) - return false; - - qreal t1 = yp; - qreal b1 = yp; - if (h < 0) - t1 += h; - else - b1 += h; - - qreal t2 = r.top(); - qreal b2 = r.top(); - if (r.height() < 0) - t2 += r.height(); - else - b2 += r.height(); - - return !(t1 >= b2 || t2 >= b1); -} - -// QRectF::intersects() returns false always if either the source or target -// rectangle's width or height are 0. This works around that problem. -static inline void _q_adjustRect(QRectF *rect) -{ - Q_ASSERT(rect); - if (!rect->width()) - rect->adjust(-0.00001, 0, 0.00001, 0); - if (!rect->height()) - rect->adjust(0, -0.00001, 0, 0.00001); -} - -static inline QRectF adjustedItemBoundingRect(const QGraphicsItem *item) -{ - Q_ASSERT(item); - QRectF boundingRect(item->boundingRect()); - _q_adjustRect(&boundingRect); - return boundingRect; -} - static void _q_hoverFromMouseEvent(QGraphicsSceneHoverEvent *hover, const QGraphicsSceneMouseEvent *mouseEvent) { hover->setWidget(mouseEvent->widget()); @@ -374,21 +315,6 @@ void QGraphicsScenePrivate::init() /*! \internal */ -QList QGraphicsScenePrivate::estimateItemsInRect(const QRectF &rect) const -{ - const_cast(this)->_q_updateSortCache(); - - // ### Only do this once in a while. - QGraphicsScenePrivate *that = const_cast(this); - - // Get items from index - return that->index->items(rect); - -} - -/*! - \internal -*/ void QGraphicsScenePrivate::_q_emitUpdated() { Q_Q(QGraphicsScene); @@ -528,7 +454,7 @@ void QGraphicsScenePrivate::_q_removeItemLater(QGraphicsItem *item) item->clearFocus(); //We ask for a removing in the index - this->index->removeItem(item, true); + this->index->deleteItem(item); // Reset the mouse grabber and focus item data. if (item == focusItem) @@ -1145,444 +1071,6 @@ QGraphicsWidget *QGraphicsScenePrivate::windowForItem(const QGraphicsItem *item) return 0; } - -QList QGraphicsScenePrivate::items_helper(const QPointF &pos) const -{ - QList items; - - // The index returns a rough estimate of what items are inside the rect. - // Refine it by iterating through all returned items. - QRectF adjustedRect = QRectF(pos, QSize(1,1)); - foreach (QGraphicsItem *item, estimateItemsInRect(adjustedRect)) { - // Find the item's scene transform in a clever way. - QTransform x = item->sceneTransform(); - bool keep = false; - - // ### _q_adjustedRect is only needed because QRectF::intersects, - // QRectF::contains and QTransform::map() and friends don't work with - // flat rectangles. - const QRectF br(adjustedItemBoundingRect(item)); - // Rect intersects/contains item's shape - if (QRectF_intersects(adjustedRect, x.mapRect(br))) { - bool ok; - QTransform xinv = x.inverted(&ok); - if (ok) { - if (item->contains(xinv.map(pos))) { - items << item; - keep = true; - } - } - } - - if (keep && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) { - // Recurse into children that clip children. - bool ok; - QTransform xinv = x.inverted(&ok); - if (ok) - childItems_helper(&items, item, xinv.map(pos)); - } - } - - sortItems(&items, Qt::AscendingOrder, sortCacheEnabled); - return items; -} - -QList QGraphicsScenePrivate::items_helper(const QRectF &rect, - Qt::ItemSelectionMode mode, - Qt::SortOrder order) const -{ - QList items; - - QPainterPath path; - - // The index returns a rough estimate of what items are inside the rect. - // Refine it by iterating through all returned items. - QRectF adjustedRect(rect); - _q_adjustRect(&adjustedRect); - foreach (QGraphicsItem *item, estimateItemsInRect(adjustedRect)) { - // Find the item's scene transform in a clever way. - QTransform x = item->sceneTransform(); - bool keep = false; - - // ### _q_adjustedRect is only needed because QRectF::intersects, - // QRectF::contains and QTransform::map() and friends don't work with - // flat rectangles. - const QRectF br(adjustedItemBoundingRect(item)); - if (mode >= Qt::ContainsItemBoundingRect) { - // Rect intersects/contains item's bounding rect - QRectF mbr = x.mapRect(br); - if ((mode == Qt::IntersectsItemBoundingRect && QRectF_intersects(rect, mbr)) - || (mode == Qt::ContainsItemBoundingRect && rect != mbr && rect.contains(mbr))) { - items << item; - keep = true; - } - } else { - // Rect intersects/contains item's shape - if (QRectF_intersects(adjustedRect, x.mapRect(br))) { - bool ok; - QTransform xinv = x.inverted(&ok); - if (ok) { - if (path.isEmpty()) - path.addRect(rect); - if (itemCollidesWithPath(item, xinv.map(path), mode)) { - items << item; - keep = true; - } - } - } - } - - if (keep && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) { - // Recurse into children that clip children. - bool ok; - QTransform xinv = x.inverted(&ok); - if (ok) { - if (x.type() <= QTransform::TxScale) { - // Rect - childItems_helper(&items, item, xinv.mapRect(rect), mode); - } else { - // Polygon - childItems_helper(&items, item, xinv.map(rect), mode); - } - } - } - } - - if (order != Qt::SortOrder(-1)) - sortItems(&items, order, sortCacheEnabled); - return items; -} - -QList QGraphicsScenePrivate::items_helper(const QPolygonF &polygon, - Qt::ItemSelectionMode mode, - Qt::SortOrder order) const -{ - QList items; - - QRectF polyRect(polygon.boundingRect()); - _q_adjustRect(&polyRect); - QPainterPath path; - - // The index returns a rough estimate of what items are inside the rect. - // Refine it by iterating through all returned items. - foreach (QGraphicsItem *item, estimateItemsInRect(polyRect)) { - // Find the item's scene transform in a clever way. - QTransform x = item->sceneTransform(); - bool keep = false; - - // ### _q_adjustedRect is only needed because QRectF::intersects, - // QRectF::contains and QTransform::map() and friends don't work with - // flat rectangles. - const QRectF br(adjustedItemBoundingRect(item)); - if (mode >= Qt::ContainsItemBoundingRect) { - // Polygon contains/intersects item's bounding rect - if (path == QPainterPath()) - path.addPolygon(polygon); - if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(x.mapRect(br))) - || (mode == Qt::ContainsItemBoundingRect && path.contains(x.mapRect(br)))) { - items << item; - keep = true; - } - } else { - // Polygon contains/intersects item's shape - if (QRectF_intersects(polyRect, x.mapRect(br))) { - bool ok; - QTransform xinv = x.inverted(&ok); - if (ok) { - if (path == QPainterPath()) - path.addPolygon(polygon); - if (itemCollidesWithPath(item, xinv.map(path), mode)) { - items << item; - keep = true; - } - } - } - } - - if (keep && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) { - // Recurse into children that clip children. - bool ok; - QTransform xinv = x.inverted(&ok); - if (ok) - childItems_helper(&items, item, xinv.map(polygon), mode); - } - } - - if (order != Qt::SortOrder(-1)) - sortItems(&items, order, sortCacheEnabled); - return items; -} - -QList QGraphicsScenePrivate::items_helper(const QPainterPath &path, - Qt::ItemSelectionMode mode, - Qt::SortOrder order) const -{ - QList items; - QRectF pathRect(path.controlPointRect()); - _q_adjustRect(&pathRect); - - // The index returns a rough estimate of what items are inside the rect. - // Refine it by iterating through all returned items. - foreach (QGraphicsItem *item, estimateItemsInRect(pathRect)) { - // Find the item's scene transform in a clever way. - QTransform x = item->sceneTransform(); - bool keep = false; - - // ### _q_adjustedRect is only needed because QRectF::intersects, - // QRectF::contains and QTransform::map() and friends don't work with - // flat rectangles. - const QRectF br(adjustedItemBoundingRect(item)); - if (mode >= Qt::ContainsItemBoundingRect) { - // Path contains/intersects item's bounding rect - if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(x.mapRect(br))) - || (mode == Qt::ContainsItemBoundingRect && path.contains(x.mapRect(br)))) { - items << item; - keep = true; - } - } else { - // Path contains/intersects item's shape - if (QRectF_intersects(pathRect, x.mapRect(br))) { - bool ok; - QTransform xinv = x.inverted(&ok); - if (ok) { - if (itemCollidesWithPath(item, xinv.map(path), mode)) { - items << item; - keep = true; - } - } - } - } - - if (keep && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) { - bool ok; - QTransform xinv = x.inverted(&ok); - if (ok) - childItems_helper(&items, item, xinv.map(path), mode); - } - } - - if (order != Qt::SortOrder(-1)) - sortItems(&items, order, sortCacheEnabled); - return items; -} - -void QGraphicsScenePrivate::childItems_helper(QList *items, - const QGraphicsItem *parent, - const QPointF &pos) const -{ - bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape); - if (parentClip && parent->d_ptr->isClippedAway()) - return; - // ### is this needed? - if (parentClip && !parent->boundingRect().contains(pos)) - return; - - QList &children = parent->d_ptr->children; - for (int i = 0; i < children.size(); ++i) { - QGraphicsItem *item = children.at(i); - if (item->d_ptr->hasTransform && !item->transform().isInvertible()) - continue; - - // Skip invisible items and all their children. - if (item->d_ptr->isInvisible()) - continue; - - bool keep = false; - if (!item->d_ptr->isClippedAway()) { - if (item->contains(item->mapFromParent(pos))) { - items->append(item); - keep = true; - } - } - - if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) - // Recurse into children. - childItems_helper(items, item, item->mapFromParent(pos)); - } -} - - -void QGraphicsScenePrivate::childItems_helper(QList *items, - const QGraphicsItem *parent, - const QRectF &rect, - Qt::ItemSelectionMode mode) const -{ - bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape); - if (parentClip && parent->d_ptr->isClippedAway()) - return; - QRectF adjustedRect(rect); - _q_adjustRect(&adjustedRect); - QRectF r = !parentClip ? adjustedRect : adjustedRect.intersected(adjustedItemBoundingRect(parent)); - if (r.isEmpty()) - return; - - QPainterPath path; - QList &children = parent->d_ptr->children; - for (int i = 0; i < children.size(); ++i) { - QGraphicsItem *item = children.at(i); - if (item->d_ptr->hasTransform && !item->transform().isInvertible()) - continue; - - // Skip invisible items and all their children. - if (item->d_ptr->isInvisible()) - continue; - - bool keep = false; - if (!item->d_ptr->isClippedAway()) { - // ### _q_adjustedRect is only needed because QRectF::intersects, - // QRectF::contains and QTransform::map() and friends don't work with - // flat rectangles. - const QRectF br(adjustedItemBoundingRect(item)); - QRectF mbr = item->mapRectToParent(br); - if (mode >= Qt::ContainsItemBoundingRect) { - // Rect intersects/contains item's bounding rect - if ((mode == Qt::IntersectsItemBoundingRect && QRectF_intersects(rect, mbr)) - || (mode == Qt::ContainsItemBoundingRect && rect != mbr && rect.contains(br))) { - items->append(item); - keep = true; - } - } else { - // Rect intersects/contains item's shape - if (QRectF_intersects(rect, mbr)) { - if (path == QPainterPath()) - path.addRect(rect); - if (itemCollidesWithPath(item, item->mapFromParent(path), mode)) { - items->append(item); - keep = true; - } - } - } - } - - if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) { - // Recurse into children. - if (!item->d_ptr->hasTransform || item->transform().type() <= QTransform::TxScale) { - // Rect - childItems_helper(items, item, item->mapRectFromParent(rect), mode); - } else { - // Polygon - childItems_helper(items, item, item->mapFromParent(rect), mode); - } - } - } -} - - -void QGraphicsScenePrivate::childItems_helper(QList *items, - const QGraphicsItem *parent, - const QPolygonF &polygon, - Qt::ItemSelectionMode mode) const -{ - bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape); - if (parentClip && parent->d_ptr->isClippedAway()) - return; - QRectF polyRect(polygon.boundingRect()); - _q_adjustRect(&polyRect); - QRectF r = !parentClip ? polyRect : polyRect.intersected(adjustedItemBoundingRect(parent)); - if (r.isEmpty()) - return; - - QPainterPath path; - QList &children = parent->d_ptr->children; - for (int i = 0; i < children.size(); ++i) { - QGraphicsItem *item = children.at(i); - if (item->d_ptr->hasTransform && !item->transform().isInvertible()) - continue; - - // Skip invisible items. - if (item->d_ptr->isInvisible()) - continue; - - bool keep = false; - if (!item->d_ptr->isClippedAway()) { - // ### _q_adjustedRect is only needed because QRectF::intersects, - // QRectF::contains and QTransform::map() and friends don't work with - // flat rectangles. - const QRectF br(adjustedItemBoundingRect(item)); - if (mode >= Qt::ContainsItemBoundingRect) { - // Polygon contains/intersects item's bounding rect - if (path == QPainterPath()) - path.addPolygon(polygon); - if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(item->mapRectToParent(br))) - || (mode == Qt::ContainsItemBoundingRect && path.contains(item->mapRectToParent(br)))) { - items->append(item); - keep = true; - } - } else { - // Polygon contains/intersects item's shape - if (QRectF_intersects(polyRect, item->mapRectToParent(br))) { - if (path == QPainterPath()) - path.addPolygon(polygon); - if (itemCollidesWithPath(item, item->mapFromParent(path), mode)) { - items->append(item); - keep = true; - } - } - } - } - - if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) { - // Recurse into children that clip children. - childItems_helper(items, item, item->mapFromParent(polygon), mode); - } - } -} - -void QGraphicsScenePrivate::childItems_helper(QList *items, - const QGraphicsItem *parent, - const QPainterPath &path, - Qt::ItemSelectionMode mode) const -{ - bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape); - if (parentClip && parent->d_ptr->isClippedAway()) - return; - QRectF pathRect(path.boundingRect()); - _q_adjustRect(&pathRect); - QRectF r = !parentClip ? pathRect : pathRect.intersected(adjustedItemBoundingRect(parent)); - if (r.isEmpty()) - return; - - QList &children = parent->d_ptr->children; - for (int i = 0; i < children.size(); ++i) { - QGraphicsItem *item = children.at(i); - if (item->d_ptr->hasTransform && !item->transform().isInvertible()) - continue; - - // Skip invisible items. - if (item->d_ptr->isInvisible()) - continue; - - bool keep = false; - if (!item->d_ptr->isClippedAway()) { - // ### _q_adjustedRect is only needed because QRectF::intersects, - // QRectF::contains and QTransform::map() and friends don't work with - // flat rectangles. - const QRectF br(adjustedItemBoundingRect(item)); - if (mode >= Qt::ContainsItemBoundingRect) { - // Polygon contains/intersects item's bounding rect - if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(item->mapRectToParent(br))) - || (mode == Qt::ContainsItemBoundingRect && path.contains(item->mapRectToParent(br)))) { - items->append(item); - keep = true; - } - } else { - // Path contains/intersects item's shape - if (QRectF_intersects(pathRect, item->mapRectToParent(br))) { - if (itemCollidesWithPath(item, item->mapFromParent(path), mode)) { - items->append(item); - keep = true; - } - } - } - } - - if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) { - // Recurse into children that clip children. - childItems_helper(items, item, item->mapFromParent(path), mode); - } - } -} - void QGraphicsScenePrivate::invalidateSortCache() { Q_Q(QGraphicsScene); @@ -1709,7 +1197,8 @@ void QGraphicsScenePrivate::climbTree(QGraphicsItem *item, int *stackingOrder) void QGraphicsScenePrivate::_q_updateSortCache() { - index->updateIndex(); + //### FIXME + //index->updateIndex(); if (!sortCacheEnabled || !updatingSortCache) return; @@ -1719,8 +1208,8 @@ void QGraphicsScenePrivate::_q_updateSortCache() QList topLevels; - for (int i = 0; i < index->indexedItems().count(); ++i) { - QGraphicsItem *item = index->indexedItems().at(i); + for (int i = 0; i < index->items().count(); ++i) { + QGraphicsItem *item = index->items().at(i); if (item && item->parentItem() == 0) topLevels << item; } @@ -1933,8 +1422,7 @@ QGraphicsScene::~QGraphicsScene() QRectF QGraphicsScene::sceneRect() const { Q_D(const QGraphicsScene); - d->index->updateIndex(); - return d->hasSceneRect ? d->index->rect() : d->growingItemsBoundingRect; + return d->hasSceneRect ? d->sceneRect : d->growingItemsBoundingRect; } void QGraphicsScene::setSceneRect(const QRectF &rect) { @@ -1942,7 +1430,7 @@ void QGraphicsScene::setSceneRect(const QRectF &rect) if (rect != d->sceneRect) { d->hasSceneRect = !rect.isNull(); d->sceneRect = rect; - d->index->setRect(rect); + d->index->sceneRectChanged(rect); emit sceneRectChanged(rect); } } @@ -2106,9 +1594,11 @@ void QGraphicsScene::setItemIndexMethod(ItemIndexMethod method) } if (d->indexMethod == CustomIndex && method == BspTreeIndex) { + //We re-add in the new index all items from the old index QGraphicsSceneIndex *oldIndex = d->index; d->index = new QGraphicsSceneBspTreeIndex(this); - d->index->insertItems(oldIndex->items(oldIndex->rect())); + for (int i = 0 ; i < oldIndex->items().size() ; ++ i) + d->index->addItem(oldIndex->items().at(i)); } if (d->indexMethod == CustomIndex && method == NoIndex) { @@ -2246,7 +1736,7 @@ QRectF QGraphicsScene::itemsBoundingRect() const QList QGraphicsScene::items() const { Q_D(const QGraphicsScene); - return d->index->indexedItems(); + return d->index->items(); } /*! @@ -2259,7 +1749,7 @@ QList QGraphicsScene::items() const QList QGraphicsScene::items(const QPointF &pos) const { Q_D(const QGraphicsScene); - return d->items_helper(pos); + return d->index->items(pos, Qt::IntersectsItemShape, Qt::AscendingOrder); } @@ -2279,7 +1769,7 @@ QList QGraphicsScene::items(const QPointF &pos) const QList QGraphicsScene::items(const QRectF &rect, Qt::ItemSelectionMode mode) const { Q_D(const QGraphicsScene); - return d->items_helper(rect, mode, Qt::AscendingOrder); + return d->index->items(rect, mode, Qt::AscendingOrder); } /*! @@ -2303,7 +1793,7 @@ QList QGraphicsScene::items(const QRectF &rect, Qt::ItemSelecti QList QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode) const { Q_D(const QGraphicsScene); - return d->items_helper(polygon, mode, Qt::AscendingOrder); + return d->index->items(polygon, mode, Qt::AscendingOrder); } /*! @@ -2320,7 +1810,74 @@ QList QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemS QList QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode) const { Q_D(const QGraphicsScene); - return d->items_helper(path, mode, Qt::AscendingOrder); + return d->index->items(path, mode, Qt::AscendingOrder); +} + +/*! + Returns all visible items at position \a pos in the scene. + + The default value for \a mode is Qt::IntersectsItemShape; all items whose + exact shape intersects with or is contained by \a path are returned. + + \sa itemAt() +*/ +QList QGraphicsScene::items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const +{ + Q_D(const QGraphicsScene); + return d->index->items(pos, mode, order, deviceTransform); +} + +/*! + \fn QList QGraphicsScene::items(const QRectF &rectangle, Qt::SortOrder order, const QTransform &deviceTransform) const + + \overload + + Returns all visible items that, depending on \a mode, are either inside or + intersect with the specified \a rectangle. + + The default value for \a mode is Qt::IntersectsItemShape; all items whose + exact shape intersects with or is contained by \a rectangle are returned. + + \sa itemAt() +*/ +QList QGraphicsScene::items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const +{ + Q_D(const QGraphicsScene); + return d->index->items(rect, mode, order, deviceTransform); +} + +/*! + \overload + + Returns all visible items that, depending on \a mode, are either inside or + intersect with the polygon \a polygon. + + The default value for \a mode is Qt::IntersectsItemShape; all items whose + exact shape intersects with or is contained by \a polygon are returned. + + \sa itemAt() +*/ +QList QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const +{ + Q_D(const QGraphicsScene); + return d->index->items(polygon, mode, order, deviceTransform); +} + +/*! + \overload + + Returns all visible items that, depending on \a path, are either inside or + intersect with the path \a path. + + The default value for \a mode is Qt::IntersectsItemShape; all items whose + exact shape intersects with or is contained by \a path are returned. + + \sa itemAt() +*/ +QList QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const +{ + Q_D(const QGraphicsScene); + return d->index->items(path, mode, order, deviceTransform); } /*! @@ -2344,10 +1901,11 @@ QList QGraphicsScene::collidingItems(const QGraphicsItem *item, } QList tmp; - foreach (QGraphicsItem *itemInVicinity, d->estimateItemsInRect(item->sceneBoundingRect())) { + foreach (QGraphicsItem *itemInVicinity, d->index->estimateItems(item->sceneBoundingRect(), Qt::AscendingOrder, QTransform())) { if (item != itemInVicinity && item->collidesWithItem(itemInVicinity, mode)) tmp << itemInVicinity; } + //### remove me d->sortItems(&tmp, Qt::AscendingOrder, d->sortCacheEnabled); return tmp; } @@ -2517,8 +2075,8 @@ void QGraphicsScene::clear() Q_D(QGraphicsScene); QList items; // Recursive descent delete - for (int i = 0; i < d->index->indexedItems().size(); ++i) { - if (QGraphicsItem *item = d->index->indexedItems().at(i)) { + for (int i = 0; i < d->index->items().size(); ++i) { + if (QGraphicsItem *item = d->index->items().at(i)) { if (!item->parentItem()) items << item; } @@ -2663,7 +2221,7 @@ void QGraphicsScene::addItem(QGraphicsItem *item) item->d_func()->scene = targetScene; // Add the item in the index - d->index->insertItem(item); + d->index->addItem(item); // Add to list of toplevels if this item is a toplevel. if (!item->d_ptr->parent) @@ -3023,7 +2581,7 @@ void QGraphicsScene::removeItem(QGraphicsItem *item) // Note: This will access item's sceneBoundingRect(), which (as this is // C++) is why we cannot call removeItem() from QGraphicsItem's // destructor. - d->index->removeItem(item, false); + d->index->deleteItem(item); if (item == d->tabFocusFirst) { QGraphicsWidget *widget = static_cast(item); diff --git a/src/gui/graphicsview/qgraphicsscene.h b/src/gui/graphicsview/qgraphicsscene.h index 6476b8c..5d70087 100644 --- a/src/gui/graphicsview/qgraphicsscene.h +++ b/src/gui/graphicsview/qgraphicsscene.h @@ -156,10 +156,17 @@ public: QRectF itemsBoundingRect() const; QList items() const; + + QList items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; + QList items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; + QList items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; + QList items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; + QList items(const QPointF &pos) const; QList items(const QRectF &rect, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; QList items(const QPolygonF &polygon, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; QList items(const QPainterPath &path, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; + QList collidingItems(const QGraphicsItem *item, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; QGraphicsItem *itemAt(const QPointF &pos) const; @@ -291,6 +298,8 @@ private: friend class QGraphicsViewPrivate; friend class QGraphicsWidget; friend class QGraphicsWidgetPrivate; + friend class QGraphicsSceneIndex; + friend class QGraphicsSceneIndexPrivate; friend class QGraphicsSceneBspTreeIndex; }; diff --git a/src/gui/graphicsview/qgraphicsscene_bsp.cpp b/src/gui/graphicsview/qgraphicsscene_bsp.cpp index f8fa450..5c1820f 100644 --- a/src/gui/graphicsview/qgraphicsscene_bsp.cpp +++ b/src/gui/graphicsview/qgraphicsscene_bsp.cpp @@ -143,7 +143,7 @@ void QGraphicsSceneBspTree::removeItems(const QSet &items) } } -QList QGraphicsSceneBspTree::items(const QRectF &rect) +QList QGraphicsSceneBspTree::items(const QRectF &rect) const { QList tmp; findVisitor->foundItems = &tmp; @@ -151,7 +151,7 @@ QList QGraphicsSceneBspTree::items(const QRectF &rect) return tmp; } -QList QGraphicsSceneBspTree::items(const QPointF &pos) +QList QGraphicsSceneBspTree::items(const QPointF &pos) const { QList tmp; findVisitor->foundItems = &tmp; @@ -235,7 +235,7 @@ void QGraphicsSceneBspTree::initialize(const QRectF &rect, int depth, int index) } } -void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QPointF &pos, int index) +void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QPointF &pos, int index) const { if (nodes.isEmpty()) return; @@ -245,7 +245,7 @@ void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, con switch (node.type) { case Node::Leaf: { - visitor->visit(&leaves[node.leafIndex]); + visitor->visit(const_cast*>(&leaves[node.leafIndex])); break; } case Node::Vertical: @@ -265,7 +265,7 @@ void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, con } } -void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QRectF &rect, int index) +void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QRectF &rect, int index) const { if (nodes.isEmpty()) return; @@ -275,7 +275,7 @@ void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, con switch (node.type) { case Node::Leaf: { - visitor->visit(&leaves[node.leafIndex]); + visitor->visit(const_cast*>(&leaves[node.leafIndex])); break; } case Node::Vertical: diff --git a/src/gui/graphicsview/qgraphicsscene_bsp_p.h b/src/gui/graphicsview/qgraphicsscene_bsp_p.h index e6ceb78..a13d862 100644 --- a/src/gui/graphicsview/qgraphicsscene_bsp_p.h +++ b/src/gui/graphicsview/qgraphicsscene_bsp_p.h @@ -92,8 +92,8 @@ public: void removeItem(QGraphicsItem *item, const QRectF &rect); void removeItems(const QSet &items); - QList items(const QRectF &rect); - QList items(const QPointF &pos); + QList items(const QRectF &rect) const; + QList items(const QPointF &pos) const; int leafCount() const; inline int firstChildIndex(int index) const @@ -106,8 +106,8 @@ public: private: void initialize(const QRectF &rect, int depth, int index); - void climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QPointF &pos, int index = 0); - void climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QRectF &rect, int index = 0); + void climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QPointF &pos, int index = 0) const; + void climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QRectF &rect, int index = 0) const; void findItems(QList *foundItems, const QRectF &rect, int index); void findItems(QList *foundItems, const QPointF &pos, int index); diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 2c0d464..a035159 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -88,8 +88,6 @@ public: QGraphicsScene::ItemIndexMethod indexMethod; int bspTreeDepth; - QList estimateItemsInRect(const QRectF &rect) const; - int lastItemCount; QGraphicsSceneIndex *index; @@ -189,33 +187,6 @@ public: void sendMouseEvent(QGraphicsSceneMouseEvent *mouseEvent); void mousePressEventHandler(QGraphicsSceneMouseEvent *mouseEvent); QGraphicsWidget *windowForItem(const QGraphicsItem *item) const; - - QList items_helper(const QPointF &pos) const; - QList items_helper(const QRectF &rect, - Qt::ItemSelectionMode mode, - Qt::SortOrder order) const; - QList items_helper(const QPolygonF &rect, - Qt::ItemSelectionMode mode, - Qt::SortOrder order) const; - QList items_helper(const QPainterPath &rect, - Qt::ItemSelectionMode mode, - Qt::SortOrder order) const; - void childItems_helper(QList *items, - const QGraphicsItem *parent, - const QPointF &pos) const; - void childItems_helper(QList *items, - const QGraphicsItem *parent, - const QRectF &rect, - Qt::ItemSelectionMode mode) const; - void childItems_helper(QList *items, - const QGraphicsItem *parent, - const QPolygonF &polygon, - Qt::ItemSelectionMode mode) const; - void childItems_helper(QList *items, - const QGraphicsItem *parent, - const QPainterPath &path, - Qt::ItemSelectionMode mode) const; - bool sortCacheEnabled; bool updatingSortCache; void invalidateSortCache(); @@ -255,6 +226,65 @@ public: mutable QVector freeSceneTransformSlots; }; +static inline bool QRectF_intersects(const QRectF &s, const QRectF &r) +{ + qreal xp = s.left(); + qreal yp = s.top(); + qreal w = s.width(); + qreal h = s.height(); + qreal l1 = xp; + qreal r1 = xp; + if (w < 0) + l1 += w; + else + r1 += w; + + qreal l2 = r.left(); + qreal r2 = r.left(); + if (w < 0) + l2 += r.width(); + else + r2 += r.width(); + + if (l1 >= r2 || l2 >= r1) + return false; + + qreal t1 = yp; + qreal b1 = yp; + if (h < 0) + t1 += h; + else + b1 += h; + + qreal t2 = r.top(); + qreal b2 = r.top(); + if (r.height() < 0) + t2 += r.height(); + else + b2 += r.height(); + + return !(t1 >= b2 || t2 >= b1); +} + +// QRectF::intersects() returns false always if either the source or target +// rectangle's width or height are 0. This works around that problem. +static inline void _q_adjustRect(QRectF *rect) +{ + Q_ASSERT(rect); + if (!rect->width()) + rect->adjust(-0.00001, 0, 0.00001, 0); + if (!rect->height()) + rect->adjust(0, -0.00001, 0, 0.00001); +} + +static inline QRectF adjustedItemBoundingRect(const QGraphicsItem *item) +{ + Q_ASSERT(item); + QRectF boundingRect(item->boundingRect()); + _q_adjustRect(&boundingRect); + return boundingRect; +} + QT_END_NAMESPACE #endif // QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp index ebc167a..1f2b81d 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp @@ -61,18 +61,6 @@ QGraphicsSceneBspTreeIndex::QGraphicsSceneBspTreeIndex(QGraphicsScene *scene) } -void QGraphicsSceneBspTreeIndex::setRect(const QRectF &rect) -{ - m_sceneRect = rect; - resetIndex(); -} - -QRectF QGraphicsSceneBspTreeIndex::rect() const -{ - const_cast(this)->updateIndex(); - return m_sceneRect; -} - void QGraphicsSceneBspTreeIndex::clear() { bsp.clear(); @@ -82,7 +70,7 @@ void QGraphicsSceneBspTreeIndex::clear() unindexedItems.clear(); } -void QGraphicsSceneBspTreeIndex::insertItem(QGraphicsItem *item) +void QGraphicsSceneBspTreeIndex::addItem(QGraphicsItem *item) { // Prevent reusing a recently deleted pointer: purge all removed items // from our lists. @@ -113,42 +101,43 @@ void QGraphicsSceneBspTreeIndex::addToIndex(QGraphicsItem *item) } } -void QGraphicsSceneBspTreeIndex::removeItem(QGraphicsItem *item, bool itemIsAboutToDie) +void QGraphicsSceneBspTreeIndex::removeItem(QGraphicsItem *item) { - if (!itemIsAboutToDie) { - // Note: This will access item's sceneBoundingRect(), which (as this is - // C++) is why we cannot call removeItem() from QGraphicsItem's - // destructor. - removeFromIndex(item); - - // Remove from our item lists. - int index = item->d_func()->index; - if (index != -1) { - freeItemIndexes << index; - m_indexedItems[index] = 0; - } else { - unindexedItems.removeAll(item); - } + // Note: This will access item's sceneBoundingRect(), which (as this is + // C++) is why we cannot call removeItem() from QGraphicsItem's + // destructor. + removeFromIndex(item); + // Remove from our item lists. + int index = item->d_func()->index; + if (index != -1) { + freeItemIndexes << index; + m_indexedItems[index] = 0; } else { - int index = item->d_func()->index; - if (index != -1) { - // Important: The index is useless until purgeRemovedItems() is - // called. - m_indexedItems[index] = (QGraphicsItem *)0; - if (!purgePending) { - purgePending = true; - scene()->update(); - } - removedItems << item; - } else { - // Recently added items are purged immediately. unindexedItems() never - // contains stale items. - unindexedItems.removeAll(item); + unindexedItems.removeAll(item); + } +} + +void QGraphicsSceneBspTreeIndex::deleteItem(QGraphicsItem *item) +{ + int index = item->d_func()->index; + if (index != -1) { + // Important: The index is useless until purgeRemovedItems() is + // called. + m_indexedItems[index] = (QGraphicsItem *)0; + if (!purgePending) { + purgePending = true; scene()->update(); } + removedItems << item; + } else { + // Recently added items are purged immediately. unindexedItems() never + // contains stale items. + unindexedItems.removeAll(item); + scene()->update(); } } + /*! \internal */ @@ -173,41 +162,17 @@ void QGraphicsSceneBspTreeIndex::removeFromIndex(QGraphicsItem *item) startIndexTimer(); } -void QGraphicsSceneBspTreeIndex::updateItem(QGraphicsItem *item) +void QGraphicsSceneBspTreeIndex::prepareBoundingRectChange(const QGraphicsItem *item) { // Note: This will access item's sceneBoundingRect(), which (as this is // C++) is why we cannot call removeItem() from QGraphicsItem's // destructor. - removeFromIndex(item); -} - -QList QGraphicsSceneBspTreeIndex::items(const QPointF &point) -{ - purgeRemovedItems(); - QList rectItems = bsp.items(QRectF(point, QSizeF(1, 1))); - // Fill in with any unindexed items - for (int i = 0; i < unindexedItems.size(); ++i) { - if (QGraphicsItem *item = unindexedItems.at(i)) { - if (!item->d_ptr->itemDiscovered && item->d_ptr->visible && !(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) { - QRectF boundingRect = item->sceneBoundingRect(); - if (boundingRect.intersects(QRectF(point, QSizeF(1, 1)))) { - item->d_ptr->itemDiscovered = 1; - rectItems << item; - } - } - } - } - - // Reset the discovered state of all discovered items - for (int i = 0; i < rectItems.size(); ++i) - rectItems.at(i)->d_func()->itemDiscovered = 0; - - return rectItems; + removeFromIndex(const_cast(item)); } -QList QGraphicsSceneBspTreeIndex::items(const QRectF &rect) +QList QGraphicsSceneBspTreeIndex::estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const { - purgeRemovedItems(); + const_cast(this)->purgeRemovedItems(); QList rectItems = bsp.items(rect); // Fill in with any unindexed items for (int i = 0; i < unindexedItems.size(); ++i) { @@ -229,9 +194,9 @@ QList QGraphicsSceneBspTreeIndex::items(const QRectF &rect) return rectItems; } -QList QGraphicsSceneBspTreeIndex::indexedItems() +QList QGraphicsSceneBspTreeIndex::items() const { - purgeRemovedItems(); + const_cast(this)->purgeRemovedItems(); // If freeItemIndexes is empty, we know there are no holes in indexedItems and // unindexedItems. if (freeItemIndexes.isEmpty()) { @@ -250,11 +215,6 @@ QList QGraphicsSceneBspTreeIndex::indexedItems() return itemList; } -void QGraphicsSceneBspTreeIndex::updateIndex() -{ - _q_updateIndex(); -} - int QGraphicsSceneBspTreeIndex::bspDepth() { return bspTreeDepth; @@ -266,6 +226,12 @@ void QGraphicsSceneBspTreeIndex::setBspDepth(int depth) resetIndex(); } +void QGraphicsSceneBspTreeIndex::sceneRectChanged(const QRectF &rect) +{ + m_sceneRect = rect; + resetIndex(); +} + bool QGraphicsSceneBspTreeIndex::event(QEvent *event) { switch (event->type()) { diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h index 74af910..63cd0e1 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h @@ -62,27 +62,23 @@ class Q_AUTOTEST_EXPORT QGraphicsSceneBspTreeIndex : public QGraphicsSceneIndex public: QGraphicsSceneBspTreeIndex(QGraphicsScene *scene = 0); - void setRect(const QRectF &rect); - virtual QRectF rect() const; - void clear(); - void insertItem(QGraphicsItem *item); - void removeItem(QGraphicsItem *item, bool itemIsAboutToDie); - void updateItem(QGraphicsItem *item); - - QList items(const QPointF &point); - QList items(const QRectF &rect); + void addItem(QGraphicsItem *item); + void removeItem(QGraphicsItem *item); + void deleteItem(QGraphicsItem *item); + void prepareBoundingRectChange(const QGraphicsItem *item); - QList indexedItems(); + QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const; - void updateIndex(); + QList items() const; int bspDepth(); void setBspDepth(int depth); protected: bool event(QEvent *event); + void sceneRectChanged(const QRectF &rect); public slots : void _q_updateIndex(); diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index 86a2fbb..870a62a 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -40,16 +40,244 @@ ****************************************************************************/ #include "qgraphicssceneindex.h" +#include "qgraphicssceneindex_p.h" #include "qgraphicsscene.h" +#include "qgraphicsitem_p.h" +#include "qgraphicsscene_p.h" #ifndef QT_NO_GRAPHICSVIEW QT_BEGIN_NAMESPACE /*! + Constructs a private scene index. +*/ +QGraphicsSceneIndexPrivate::QGraphicsSceneIndexPrivate(QGraphicsScene *scene) : scene(scene) +{ +} + +void QGraphicsSceneIndexPrivate::childItems_helper(QList *items, + const QGraphicsItem *parent, + const QPointF &pos) const +{ + bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape); + if (parentClip && parent->d_ptr->isClippedAway()) + return; + // ### is this needed? + if (parentClip && !parent->boundingRect().contains(pos)) + return; + + QList &children = parent->d_ptr->children; + for (int i = 0; i < children.size(); ++i) { + QGraphicsItem *item = children.at(i); + if (item->d_ptr->hasTransform && !item->transform().isInvertible()) + continue; + + // Skip invisible items and all their children. + if (item->d_ptr->isInvisible()) + continue; + + bool keep = false; + if (!item->d_ptr->isClippedAway()) { + if (item->contains(item->mapFromParent(pos))) { + items->append(item); + keep = true; + } + } + + if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) + // Recurse into children. + childItems_helper(items, item, item->mapFromParent(pos)); + } +} + + +void QGraphicsSceneIndexPrivate::childItems_helper(QList *items, + const QGraphicsItem *parent, + const QRectF &rect, + Qt::ItemSelectionMode mode) const +{ + bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape); + if (parentClip && parent->d_ptr->isClippedAway()) + return; + QRectF adjustedRect(rect); + _q_adjustRect(&adjustedRect); + QRectF r = !parentClip ? adjustedRect : adjustedRect.intersected(adjustedItemBoundingRect(parent)); + if (r.isEmpty()) + return; + + QPainterPath path; + QList &children = parent->d_ptr->children; + for (int i = 0; i < children.size(); ++i) { + QGraphicsItem *item = children.at(i); + if (item->d_ptr->hasTransform && !item->transform().isInvertible()) + continue; + + // Skip invisible items and all their children. + if (item->d_ptr->isInvisible()) + continue; + + bool keep = false; + if (!item->d_ptr->isClippedAway()) { + // ### _q_adjustedRect is only needed because QRectF::intersects, + // QRectF::contains and QTransform::map() and friends don't work with + // flat rectangles. + const QRectF br(adjustedItemBoundingRect(item)); + QRectF mbr = item->mapRectToParent(br); + if (mode >= Qt::ContainsItemBoundingRect) { + // Rect intersects/contains item's bounding rect + if ((mode == Qt::IntersectsItemBoundingRect && QRectF_intersects(rect, mbr)) + || (mode == Qt::ContainsItemBoundingRect && rect != mbr && rect.contains(br))) { + items->append(item); + keep = true; + } + } else { + // Rect intersects/contains item's shape + if (QRectF_intersects(rect, mbr)) { + if (path == QPainterPath()) + path.addRect(rect); + if (scene->d_func()->itemCollidesWithPath(item, item->mapFromParent(path), mode)) { + items->append(item); + keep = true; + } + } + } + } + + if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) { + // Recurse into children. + if (!item->d_ptr->hasTransform || item->transform().type() <= QTransform::TxScale) { + // Rect + childItems_helper(items, item, item->mapRectFromParent(rect), mode); + } else { + // Polygon + childItems_helper(items, item, item->mapFromParent(rect), mode); + } + } + } +} + + +void QGraphicsSceneIndexPrivate::childItems_helper(QList *items, + const QGraphicsItem *parent, + const QPolygonF &polygon, + Qt::ItemSelectionMode mode) const +{ + bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape); + if (parentClip && parent->d_ptr->isClippedAway()) + return; + QRectF polyRect(polygon.boundingRect()); + _q_adjustRect(&polyRect); + QRectF r = !parentClip ? polyRect : polyRect.intersected(adjustedItemBoundingRect(parent)); + if (r.isEmpty()) + return; + + QPainterPath path; + QList &children = parent->d_ptr->children; + for (int i = 0; i < children.size(); ++i) { + QGraphicsItem *item = children.at(i); + if (item->d_ptr->hasTransform && !item->transform().isInvertible()) + continue; + + // Skip invisible items. + if (item->d_ptr->isInvisible()) + continue; + + bool keep = false; + if (!item->d_ptr->isClippedAway()) { + // ### _q_adjustedRect is only needed because QRectF::intersects, + // QRectF::contains and QTransform::map() and friends don't work with + // flat rectangles. + const QRectF br(adjustedItemBoundingRect(item)); + if (mode >= Qt::ContainsItemBoundingRect) { + // Polygon contains/intersects item's bounding rect + if (path == QPainterPath()) + path.addPolygon(polygon); + if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(item->mapRectToParent(br))) + || (mode == Qt::ContainsItemBoundingRect && path.contains(item->mapRectToParent(br)))) { + items->append(item); + keep = true; + } + } else { + // Polygon contains/intersects item's shape + if (QRectF_intersects(polyRect, item->mapRectToParent(br))) { + if (path == QPainterPath()) + path.addPolygon(polygon); + if (scene->d_func()->itemCollidesWithPath(item, item->mapFromParent(path), mode)) { + items->append(item); + keep = true; + } + } + } + } + + if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) { + // Recurse into children that clip children. + childItems_helper(items, item, item->mapFromParent(polygon), mode); + } + } +} + +void QGraphicsSceneIndexPrivate::childItems_helper(QList *items, + const QGraphicsItem *parent, + const QPainterPath &path, + Qt::ItemSelectionMode mode) const +{ + bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape); + if (parentClip && parent->d_ptr->isClippedAway()) + return; + QRectF pathRect(path.boundingRect()); + _q_adjustRect(&pathRect); + QRectF r = !parentClip ? pathRect : pathRect.intersected(adjustedItemBoundingRect(parent)); + if (r.isEmpty()) + return; + + QList &children = parent->d_ptr->children; + for (int i = 0; i < children.size(); ++i) { + QGraphicsItem *item = children.at(i); + if (item->d_ptr->hasTransform && !item->transform().isInvertible()) + continue; + + // Skip invisible items. + if (item->d_ptr->isInvisible()) + continue; + + bool keep = false; + if (!item->d_ptr->isClippedAway()) { + // ### _q_adjustedRect is only needed because QRectF::intersects, + // QRectF::contains and QTransform::map() and friends don't work with + // flat rectangles. + const QRectF br(adjustedItemBoundingRect(item)); + if (mode >= Qt::ContainsItemBoundingRect) { + // Polygon contains/intersects item's bounding rect + if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(item->mapRectToParent(br))) + || (mode == Qt::ContainsItemBoundingRect && path.contains(item->mapRectToParent(br)))) { + items->append(item); + keep = true; + } + } else { + // Path contains/intersects item's shape + if (QRectF_intersects(pathRect, item->mapRectToParent(br))) { + if (scene->d_func()->itemCollidesWithPath(item, item->mapFromParent(path), mode)) { + items->append(item); + keep = true; + } + } + } + } + + if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) { + // Recurse into children that clip children. + childItems_helper(items, item, item->mapFromParent(path), mode); + } + } +} + +/*! Constructs an abstract scene index. */ -QGraphicsSceneIndex::QGraphicsSceneIndex(QGraphicsScene *scene): QObject(scene), m_scene(scene) +QGraphicsSceneIndex::QGraphicsSceneIndex(QGraphicsScene *scene) +: QObject(*new QGraphicsSceneIndexPrivate(scene)) { } @@ -62,109 +290,325 @@ QGraphicsSceneIndex::~QGraphicsSceneIndex() } /*! - \fn virtual void setRect(const QRectF &rect) = 0 - - This pure virtual function is called when the scene changes its bounding - rectangle. - - \sa rect(), QGraphicsScene::setSceneRect + Returns the scene of this index. */ - +QGraphicsScene* QGraphicsSceneIndex::scene() const +{ + Q_D(const QGraphicsSceneIndex); + return d->scene; +} /*! - \fn virtual QRectF rect() const = 0 + \fn QList items() const = 0 - This pure virtual function returns the bounding rectangle of this - scene index. It could be as large as or larger than the scene - bounding rectangle, depending on the implementation of the - scene index. + This pure virtual function return the list of items that are actually in the index. - \sa setRect(), QGraphicsScene::sceneRect */ -/*! - \fn virtual void clear() = 0 +QList QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const +{ + Q_D(const QGraphicsSceneIndex); + QList items; + + // The index returns a rough estimate of what items are inside the rect. + // Refine it by iterating through all returned items. + QRectF adjustedRect = QRectF(pos, QSize(1,1)); + foreach (QGraphicsItem *item, estimateItems(adjustedRect, order, deviceTransform)) { + // Find the item's scene transform in a clever way. + QTransform x = item->sceneTransform(); + bool keep = false; + + // ### _q_adjustedRect is only needed because QRectF::intersects, + // QRectF::contains and QTransform::map() and friends don't work with + // flat rectangles. + const QRectF br(adjustedItemBoundingRect(item)); + // Rect intersects/contains item's shape + if (QRectF_intersects(adjustedRect, x.mapRect(br))) { + bool ok; + QTransform xinv = x.inverted(&ok); + if (ok) { + if (item->contains(xinv.map(pos))) { + items << item; + keep = true; + } + } + } + + if (keep && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) { + // Recurse into children that clip children. + bool ok; + QTransform xinv = x.inverted(&ok); + if (ok) + d->childItems_helper(&items, item, xinv.map(pos)); + } + } + + d->scene->d_func()->sortItems(&items, Qt::AscendingOrder, d->scene->d_func()->sortCacheEnabled); + return items; +} - This pure virtual function removes all items in the scene index. -*/ +QList QGraphicsSceneIndex::items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const +{ + Q_D(const QGraphicsSceneIndex); + QList items; + + QPainterPath path; + + // The index returns a rough estimate of what items are inside the rect. + // Refine it by iterating through all returned items. + QRectF adjustedRect(rect); + _q_adjustRect(&adjustedRect); + foreach (QGraphicsItem *item, estimateItems(adjustedRect, order, deviceTransform)) { + // Find the item's scene transform in a clever way. + QTransform x = item->sceneTransform(); + bool keep = false; + + // ### _q_adjustedRect is only needed because QRectF::intersects, + // QRectF::contains and QTransform::map() and friends don't work with + // flat rectangles. + const QRectF br(adjustedItemBoundingRect(item)); + if (mode >= Qt::ContainsItemBoundingRect) { + // Rect intersects/contains item's bounding rect + QRectF mbr = x.mapRect(br); + if ((mode == Qt::IntersectsItemBoundingRect && QRectF_intersects(rect, mbr)) + || (mode == Qt::ContainsItemBoundingRect && rect != mbr && rect.contains(mbr))) { + items << item; + keep = true; + } + } else { + // Rect intersects/contains item's shape + if (QRectF_intersects(adjustedRect, x.mapRect(br))) { + bool ok; + QTransform xinv = x.inverted(&ok); + if (ok) { + if (path.isEmpty()) + path.addRect(rect); + if (d->scene->d_func()->itemCollidesWithPath(item, xinv.map(path), mode)) { + items << item; + keep = true; + } + } + } + } + + if (keep && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) { + // Recurse into children that clip children. + bool ok; + QTransform xinv = x.inverted(&ok); + if (ok) { + if (x.type() <= QTransform::TxScale) { + // Rect + d->childItems_helper(&items, item, xinv.mapRect(rect), mode); + } else { + // Polygon + d->childItems_helper(&items, item, xinv.map(rect), mode); + } + } + } + } + + if (order != Qt::SortOrder(-1)) + d->scene->d_func()->sortItems(&items, order, d->scene->d_func()->sortCacheEnabled); + return items; +} -/*! - \fn virtual void insertItem(QGraphicsItem *item) = 0 +QList QGraphicsSceneIndex::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const +{ + Q_D(const QGraphicsSceneIndex); + QList items; + + QRectF polyRect(polygon.boundingRect()); + _q_adjustRect(&polyRect); + QPainterPath path; + + // The index returns a rough estimate of what items are inside the rect. + // Refine it by iterating through all returned items. + foreach (QGraphicsItem *item, estimateItems(polyRect, order, deviceTransform)) { + // Find the item's scene transform in a clever way. + QTransform x = item->sceneTransform(); + bool keep = false; + + // ### _q_adjustedRect is only needed because QRectF::intersects, + // QRectF::contains and QTransform::map() and friends don't work with + // flat rectangles. + const QRectF br(adjustedItemBoundingRect(item)); + if (mode >= Qt::ContainsItemBoundingRect) { + // Polygon contains/intersects item's bounding rect + if (path == QPainterPath()) + path.addPolygon(polygon); + if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(x.mapRect(br))) + || (mode == Qt::ContainsItemBoundingRect && path.contains(x.mapRect(br)))) { + items << item; + keep = true; + } + } else { + // Polygon contains/intersects item's shape + if (QRectF_intersects(polyRect, x.mapRect(br))) { + bool ok; + QTransform xinv = x.inverted(&ok); + if (ok) { + if (path == QPainterPath()) + path.addPolygon(polygon); + if (d->scene->d_func()->itemCollidesWithPath(item, xinv.map(path), mode)) { + items << item; + keep = true; + } + } + } + } + + if (keep && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) { + // Recurse into children that clip children. + bool ok; + QTransform xinv = x.inverted(&ok); + if (ok) + d->childItems_helper(&items, item, xinv.map(polygon), mode); + } + } + + if (order != Qt::SortOrder(-1)) + d->scene->d_func()->sortItems(&items, order, d->scene->d_func()->sortCacheEnabled); + return items; +} +QList QGraphicsSceneIndex::items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const +{ + Q_D(const QGraphicsSceneIndex); + QList items; + QRectF pathRect(path.controlPointRect()); + _q_adjustRect(&pathRect); + + // The index returns a rough estimate of what items are inside the rect. + // Refine it by iterating through all returned items. + foreach (QGraphicsItem *item, estimateItems(pathRect, order, deviceTransform)) { + // Find the item's scene transform in a clever way. + QTransform x = item->sceneTransform(); + bool keep = false; + + // ### _q_adjustedRect is only needed because QRectF::intersects, + // QRectF::contains and QTransform::map() and friends don't work with + // flat rectangles. + const QRectF br(adjustedItemBoundingRect(item)); + if (mode >= Qt::ContainsItemBoundingRect) { + // Path contains/intersects item's bounding rect + if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(x.mapRect(br))) + || (mode == Qt::ContainsItemBoundingRect && path.contains(x.mapRect(br)))) { + items << item; + keep = true; + } + } else { + // Path contains/intersects item's shape + if (QRectF_intersects(pathRect, x.mapRect(br))) { + bool ok; + QTransform xinv = x.inverted(&ok); + if (ok) { + if (d->scene->d_func()->itemCollidesWithPath(item, xinv.map(path), mode)) { + items << item; + keep = true; + } + } + } + } + + if (keep && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) { + bool ok; + QTransform xinv = x.inverted(&ok); + if (ok) + d->childItems_helper(&items, item, xinv.map(path), mode); + } + } + + if (order != Qt::SortOrder(-1)) + d->scene->d_func()->sortItems(&items, order, d->scene->d_func()->sortCacheEnabled); + return items; +} - This pure virtual function inserts an item to the scene index. +/*! + This pure virtual function return an estimation of items at position \a pos. - \sa removeItem(), updateItem(), insertItems() */ +QList QGraphicsSceneIndex::estimateItems(const QPointF &point, Qt::SortOrder order, const QTransform &deviceTransform) const +{ + return estimateItems(QRectF(point, QSize(1,1)), order, deviceTransform); +} /*! - \fn virtual void removeItem(QGraphicsItem *item) = 0 + \fn virtual QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const = 0 - This pure virtual function removes an item to the scene index. + This pure virtual function return an estimation of items in the \a rect. - \sa insertItem(), updateItem(), removeItems() */ + /*! - Returns the scene of this index. + This virtual function removes all items in the scene index. */ -QGraphicsScene* QGraphicsSceneIndex::scene() const +void QGraphicsSceneIndex::clear() { - return m_scene; + for (int i = 0 ; i < items().size(); ++i) + removeItem(items().at(i)); } /*! - Updates an item when its geometry has changed. + \fn virtual void addItem(QGraphicsItem *item) = 0 - The default implemention will remove the item from the index - and then insert it again. + This pure virtual function inserts an item to the scene index. - \sa insertItem(), removeItem(), updateItems() + \sa removeItem(), deleteItem() */ -void QGraphicsSceneIndex::updateItem(QGraphicsItem *item) -{ - removeItem(item,false); - insertItem(item); -} /*! - Inserts a list of items to the index. + \fn virtual void removeItem(QGraphicsItem *item) = 0 - The default implemention will insert the items one by one. + This pure virtual function removes an item to the scene index. - \sa insertItem(), removeItems(), updateItems() + \sa addItem(), deleteItem() */ -void QGraphicsSceneIndex::insertItems(const QList &items) + +/*! + This method is called when an item has been deleted. + The default implementation call removeItem. Be carefull, + if your implementation of removeItem use pure virtual method + of QGraphicsItem like boundingRect(), then you should reimplement + this method. + + \sa addItem(), removeItem() +*/ +void QGraphicsSceneIndex::deleteItem(QGraphicsItem *item) { - foreach (QGraphicsItem *item, items) - insertItem(item); + removeItem(item); } /*! - Removes a list of items from the index. + This virtual function is called by QGraphicsItem to notify the index + that some part of the item's state changes. By reimplementing this + function, your can react to a change, and in some cases, (depending on \a + change,) adjustments in the index can be made. - The default implemention will remove the items one by one. + \a change is the parameter of the item that is changing. \a value is the + value that changed; the type of the value depends on \a change. - \sa removeItem(), removeItems(), updateItems() + The default implementation does nothing. + + \sa GraphicsItemChange */ -void QGraphicsSceneIndex::removeItems(const QList &items, bool itemsAreAboutToDie) +void QGraphicsSceneIndex::itemChanged(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange, const QVariant &value) { - foreach (QGraphicsItem *item, items) - removeItem(item,itemsAreAboutToDie); } /*! - Update a list of items which have changed the geometry. - - The default implemention will update the items one by one. + Notify the index for a geometry change of an item. - \sa updateItem(), insertItems(), removeItems() + \sa QGraphicsItem::prepareGeometryChange */ -void QGraphicsSceneIndex::updateItems(const QList &items) +void QGraphicsSceneIndex::prepareBoundingRectChange(const QGraphicsItem *item) { - foreach (QGraphicsItem *item, items) - updateItem(item); } -void QGraphicsSceneIndex::updateIndex() +/*! + This virtual function is called when the scene changes its bounding + rectangle. + \sa QGraphicsScene::sceneRect +*/ +void QGraphicsSceneIndex::sceneRectChanged(const QRectF &rect) { } diff --git a/src/gui/graphicsview/qgraphicssceneindex.h b/src/gui/graphicsview/qgraphicssceneindex.h index a782323..da3096e 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.h +++ b/src/gui/graphicsview/qgraphicssceneindex.h @@ -44,6 +44,8 @@ #include #include +#include +#include QT_BEGIN_HEADER @@ -53,7 +55,7 @@ QT_MODULE(Gui) #if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW -class QGraphicsItem; +class QGraphicsSceneIndexPrivate; class QGraphicsScene; class QRectF; class QPointF; @@ -67,29 +69,31 @@ public: QGraphicsSceneIndex(QGraphicsScene *scene = 0); virtual ~QGraphicsSceneIndex(); - QGraphicsScene* scene() const; - - virtual void setRect(const QRectF &rect) = 0; - virtual QRectF rect() const = 0; - virtual void clear() = 0; - - virtual void insertItem(QGraphicsItem *item) = 0; - virtual void removeItem(QGraphicsItem *items, bool itemIsAboutToDie) = 0; - virtual void updateItem(QGraphicsItem *item); - - virtual void insertItems(const QList &items); - virtual void removeItems(const QList &items, bool itemsAreAboutToDie); - virtual void updateItems(const QList &items); - - virtual QList items(const QPointF &point) = 0; - virtual QList items(const QRectF &rect) = 0; - - virtual QList indexedItems() = 0; - - virtual void updateIndex(); - + QGraphicsScene *scene() const; + + virtual QList items() const = 0; + virtual QList items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; + virtual QList items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; + virtual QList items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; + virtual QList items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; + virtual QList estimateItems(const QPointF &point, Qt::SortOrder order, const QTransform &deviceTransform) const; + virtual QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const = 0; + +protected: + virtual void clear(); + virtual void addItem(QGraphicsItem *item) = 0; + virtual void removeItem(QGraphicsItem *item) = 0; + virtual void deleteItem(QGraphicsItem *item); + + virtual void itemChanged(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange, const QVariant &value); + virtual void prepareBoundingRectChange(const QGraphicsItem *item); + virtual void sceneRectChanged(const QRectF &rect); + + friend class QGraphicsScene; + friend class QGraphicsScenePrivate; + friend class QGraphicsItem; private: - QGraphicsScene *m_scene; + Q_DECLARE_PRIVATE(QGraphicsSceneIndex) }; #endif // QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicssceneindex_p.h b/src/gui/graphicsview/qgraphicssceneindex_p.h new file mode 100644 index 0000000..f2cdca3 --- /dev/null +++ b/src/gui/graphicsview/qgraphicssceneindex_p.h @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGRAPHICSSCENEINDEX_P_H +#define QGRAPHICSSCENEINDEX_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header +// file may change from version to version without notice, or even be removed. +// +// We mean it. +// + +#include "qgraphicssceneindex.h" + +#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW + +#include + +QT_BEGIN_NAMESPACE + +class QGraphicsScene; + +class QGraphicsSceneIndexPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QGraphicsSceneIndex) +public: + QGraphicsSceneIndexPrivate(QGraphicsScene *scene); + + + void childItems_helper(QList *items, + const QGraphicsItem *parent, + const QPointF &pos) const; + void childItems_helper(QList *items, + const QGraphicsItem *parent, + const QRectF &rect, + Qt::ItemSelectionMode mode) const; + void childItems_helper(QList *items, + const QGraphicsItem *parent, + const QPolygonF &polygon, + Qt::ItemSelectionMode mode) const; + void childItems_helper(QList *items, + const QGraphicsItem *parent, + const QPainterPath &path, + Qt::ItemSelectionMode mode) const; + + QGraphicsScene *scene; +}; + +QT_END_NAMESPACE + +#endif // QGRAPHICSSCENEINDEX_P_H + +#endif diff --git a/src/gui/graphicsview/qgraphicsscenelinearindex_p.h b/src/gui/graphicsview/qgraphicsscenelinearindex_p.h index 30948d9..dc45a17 100644 --- a/src/gui/graphicsview/qgraphicsscenelinearindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenelinearindex_p.h @@ -89,24 +89,15 @@ public: m_items.clear(); } - virtual void insertItem(QGraphicsItem *item) { + virtual void addItem(QGraphicsItem *item) { m_items << item; } - virtual void removeItem(QGraphicsItem *item, bool itemIsAboutToDie) { - Q_UNUSED(itemIsAboutToDie); + virtual void removeItem(QGraphicsItem *item) { m_items.removeAll(item); } - virtual QList items(const QPointF &point) { - QList result; - foreach (QGraphicsItem *item, m_items) - if (item->sceneBoundingRect().contains(point)) - result << item; - return result; - } - - virtual QList items(const QRectF &rect) { + virtual QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const { QList result; foreach (QGraphicsItem *item, m_items) if (item->sceneBoundingRect().intersects(rect)) @@ -114,7 +105,7 @@ public: return result; } - QList indexedItems() { + QList items() const { return m_items; } }; diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 10b837a..91f97a1 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -791,19 +791,6 @@ QRegion QGraphicsViewPrivate::mapToViewRegion(const QGraphicsItem *item, const Q return item->boundingRegion(itv) & itv.mapRect(rect).toAlignedRect(); } -// QRectF::intersects() returns false always if either the source or target -// rectangle's width or height are 0. This works around that problem. -static inline QRectF adjustedItemBoundingRect(const QGraphicsItem *item) -{ - Q_ASSERT(item); - QRectF boundingRect(item->boundingRect()); - if (!boundingRect.width()) - boundingRect.adjust(-0.00001, 0, 0.00001, 0); - if (!boundingRect.height()) - boundingRect.adjust(0, -0.00001, 0, 0.00001); - return boundingRect; -} - /*! \internal */ @@ -1094,7 +1081,7 @@ QList QGraphicsViewPrivate::findItems(const QRegion &exposedReg bool simpleRectLookup = (scene->d_func()->largestUntransformableItem.isNull() && exposedRegion.numRects() == 1 && matrix.type() <= QTransform::TxScale); if (simpleRectLookup) { - return scene->d_func()->items_helper(exposedRegionSceneBounds, + return scene->d_func()->index->items(exposedRegionSceneBounds, Qt::IntersectsItemBoundingRect, Qt::DescendingOrder); } @@ -1109,7 +1096,7 @@ QList QGraphicsViewPrivate::findItems(const QRegion &exposedReg const QPainterPath exposedPath(qt_regionToPath(adjustedRegion)); if (scene->d_func()->largestUntransformableItem.isNull()) { const QPainterPath exposedScenePath(q->mapToScene(exposedPath)); - return scene->d_func()->items_helper(exposedScenePath, + return scene->d_func()->index->items(exposedScenePath, Qt::IntersectsItemBoundingRect, Qt::DescendingOrder); } @@ -2143,7 +2130,7 @@ QList QGraphicsViewPrivate::itemsInArea(const QPainterPath &pat // First build a (potentially large) list of all items in the vicinity // that might be untransformable. - QList allCandidates = scene->d_func()->estimateItemsInRect(adjustedRect); + QList allCandidates = scene->d_func()->index->estimateItems(adjustedRect, order, q->transform()); // Then find the minimal list of items that are inside \a path, and // convert it to a set. @@ -2154,6 +2141,8 @@ QList QGraphicsViewPrivate::itemsInArea(const QPainterPath &pat QList result; + //### this will disapear + // Run through all candidates and keep all items that are in candSet, or // are untransformable and collide with \a path. ### We can improve this // algorithm. -- cgit v0.12 From 32155ed07a6f8b8c831db6ba219395b4825fa9fd Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Fri, 29 May 2009 15:15:58 +0200 Subject: Fix a wrong parenting. --- src/gui/graphicsview/qgraphicssceneindex.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index 870a62a..36da295 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -277,7 +277,7 @@ void QGraphicsSceneIndexPrivate::childItems_helper(QList *items Constructs an abstract scene index. */ QGraphicsSceneIndex::QGraphicsSceneIndex(QGraphicsScene *scene) -: QObject(*new QGraphicsSceneIndexPrivate(scene)) +: QObject(*new QGraphicsSceneIndexPrivate(scene), scene) { } -- cgit v0.12 From 53187fabdbfb8a513e735fdd034e1a9fbbccc9cd Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Fri, 29 May 2009 17:18:38 +0200 Subject: Add an API to know the indexed rect of the index. Usefull for the POV of the scene and let the BSP update its internal structure before the next event loop reentrancy. --- src/gui/graphicsview/qgraphicsscene.cpp | 2 +- src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp | 7 +++++++ src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h | 1 + src/gui/graphicsview/qgraphicssceneindex.cpp | 10 ++++++++++ src/gui/graphicsview/qgraphicssceneindex.h | 2 ++ 5 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 9b6d40b..479a548 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -1422,7 +1422,7 @@ QGraphicsScene::~QGraphicsScene() QRectF QGraphicsScene::sceneRect() const { Q_D(const QGraphicsScene); - return d->hasSceneRect ? d->sceneRect : d->growingItemsBoundingRect; + return d->index->indexedRect(); } void QGraphicsScene::setSceneRect(const QRectF &rect) { diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp index 1f2b81d..8a26447 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp @@ -61,6 +61,13 @@ QGraphicsSceneBspTreeIndex::QGraphicsSceneBspTreeIndex(QGraphicsScene *scene) } + +QRectF QGraphicsSceneBspTreeIndex::indexedRect() +{ + _q_updateIndex(); + return scene()->d_func()->hasSceneRect ? scene()->d_func()->sceneRect : scene()->d_func()->growingItemsBoundingRect; +} + void QGraphicsSceneBspTreeIndex::clear() { bsp.clear(); diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h index 63cd0e1..7a6ea0b 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h @@ -61,6 +61,7 @@ class Q_AUTOTEST_EXPORT QGraphicsSceneBspTreeIndex : public QGraphicsSceneIndex Q_OBJECT public: QGraphicsSceneBspTreeIndex(QGraphicsScene *scene = 0); + QRectF indexedRect(); void clear(); diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index 36da295..fe3a68a 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -297,6 +297,16 @@ QGraphicsScene* QGraphicsSceneIndex::scene() const Q_D(const QGraphicsSceneIndex); return d->scene; } + +/*! + Returns the indexed area for the index +*/ +QRectF QGraphicsSceneIndex::indexedRect() +{ + Q_D(const QGraphicsSceneIndex); + return d->scene->d_func()->sceneRect; +} + /*! \fn QList items() const = 0 diff --git a/src/gui/graphicsview/qgraphicssceneindex.h b/src/gui/graphicsview/qgraphicssceneindex.h index da3096e..11d9aae 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.h +++ b/src/gui/graphicsview/qgraphicssceneindex.h @@ -71,6 +71,8 @@ public: QGraphicsScene *scene() const; + virtual QRectF indexedRect(); + virtual QList items() const = 0; virtual QList items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; virtual QList items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; -- cgit v0.12 From 4785ed9b76104c272476f62780dde086e21b20ce Mon Sep 17 00:00:00 2001 From: Tobias Koenig Date: Sun, 31 May 2009 13:28:18 +0200 Subject: Add conformance section to qtxmlpatterns doc and extended api docs --- doc/src/qtxmlpatterns.qdoc | 21 +++++++++++++++++++++ src/xmlpatterns/api/qxmlschemavalidator.cpp | 8 +++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/doc/src/qtxmlpatterns.qdoc b/doc/src/qtxmlpatterns.qdoc index cb260fc..a48d713 100644 --- a/doc/src/qtxmlpatterns.qdoc +++ b/doc/src/qtxmlpatterns.qdoc @@ -839,6 +839,27 @@ with the \c fn:id() function. See \l{http://www.w3.org/TR/xml-id/}{xml:id Version 1.0} for details. + \section2 XML Schema 1.0 + + The QtXmlPatterns implementation of XML Schema validation supports + the schema specification version 1.0 in large parts. Known problems + of the implementation and areas where conformancy may be questionable + are: + + \list + \o Large \c minOccurs or \c maxOccurs values or deeply nested ones + require huge amount of memory which might cause the system to freeze. + Such a schema should be rewritten to use \c unbounded as value instead + of large numbers. This restriction will hopefully be fixed in a later release. + \o Comparison of really small or large floating point values might lead to + wrong results in some cases. However such numbers should not be relevant + for day-to-day usage. + \o Regular expression support is currently not conformant but follows + Qt's QRegExp standard syntax. + \o Identity constraint checks can not use the values of default or fixed + attribute definitions. + \endlist + \section2 Resource Loading When QtXmlPatterns loads an XML resource, e.g., using the diff --git a/src/xmlpatterns/api/qxmlschemavalidator.cpp b/src/xmlpatterns/api/qxmlschemavalidator.cpp index b72b1ef..dc8e55d 100644 --- a/src/xmlpatterns/api/qxmlschemavalidator.cpp +++ b/src/xmlpatterns/api/qxmlschemavalidator.cpp @@ -69,7 +69,7 @@ /*! Constructs a schema validator. The schema used for validation must be referenced in the XML instance document - via the xsi:schemaLocation attribute. + via the \c xsi:schemaLocation or \c xsi:noNamespaceSchemaLocation attribute. */ QXmlSchemaValidator::QXmlSchemaValidator() : d(new QXmlSchemaValidatorPrivate(QXmlSchema())) @@ -78,6 +78,9 @@ QXmlSchemaValidator::QXmlSchemaValidator() /*! Constructs a schema validator that will use \a schema for validation. + If an empty \l {QXmlSchema} schema is passed to the validator, the schema used + for validation must be referenced in the XML instance document + via the \c xsi:schemaLocation or \c xsi:noNamespaceSchemaLocation attribute. */ QXmlSchemaValidator::QXmlSchemaValidator(const QXmlSchema &schema) : d(new QXmlSchemaValidatorPrivate(schema)) @@ -94,6 +97,9 @@ QXmlSchemaValidator::~QXmlSchemaValidator() /*! Sets the \a schema that shall be used for further validation. + If the schema is empty, the schema used for validation must be referenced + in the XML instance document via the \c xsi:schemaLocation or + \c xsi:noNamespaceSchemaLocation attribute. */ void QXmlSchemaValidator::setSchema(const QXmlSchema &schema) { -- cgit v0.12 From 427c4d6b0a8b3004c86facd382de33c171c0458b Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Tue, 2 Jun 2009 17:45:27 +0200 Subject: Fix all auto-tests regressions. --- src/gui/graphicsview/qgraphicsscene.cpp | 15 +++++++++------ src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp | 11 ++++++----- src/gui/graphicsview/qgraphicssceneindex.cpp | 2 +- tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp | 3 +++ .../auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp | 4 ++-- 5 files changed, 21 insertions(+), 14 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 479a548..0172a23 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -453,7 +453,9 @@ void QGraphicsScenePrivate::_q_removeItemLater(QGraphicsItem *item) // chain. item->clearFocus(); - //We ask for a removing in the index + // Note: This will access item's sceneBoundingRect(), which (as this is + // C++) is why we cannot call removeItem() from QGraphicsItem's + // destructor. this->index->deleteItem(item); // Reset the mouse grabber and focus item data. @@ -1198,7 +1200,10 @@ void QGraphicsScenePrivate::climbTree(QGraphicsItem *item, int *stackingOrder) void QGraphicsScenePrivate::_q_updateSortCache() { //### FIXME - //index->updateIndex(); + QGraphicsSceneBspTreeIndex *tree = qobject_cast(index); + if (tree) { + tree->_q_updateIndex(); + } if (!sortCacheEnabled || !updatingSortCache) return; @@ -2578,10 +2583,8 @@ void QGraphicsScene::removeItem(QGraphicsItem *item) // Clear its background item->update(); - // Note: This will access item's sceneBoundingRect(), which (as this is - // C++) is why we cannot call removeItem() from QGraphicsItem's - // destructor. - d->index->deleteItem(item); + // Remove it from the index properly + d->index->removeItem(item); if (item == d->tabFocusFirst) { QGraphicsWidget *widget = static_cast(item); diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp index 8a26447..f8f1f56 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp @@ -61,11 +61,10 @@ QGraphicsSceneBspTreeIndex::QGraphicsSceneBspTreeIndex(QGraphicsScene *scene) } - QRectF QGraphicsSceneBspTreeIndex::indexedRect() { _q_updateIndex(); - return scene()->d_func()->hasSceneRect ? scene()->d_func()->sceneRect : scene()->d_func()->growingItemsBoundingRect; + return scene()->d_func()->hasSceneRect ? scene()->d_func()->sceneRect : scene()->d_func()->growingItemsBoundingRect; } void QGraphicsSceneBspTreeIndex::clear() @@ -162,7 +161,7 @@ void QGraphicsSceneBspTreeIndex::removeFromIndex(QGraphicsItem *item) item->d_func()->index = -1; unindexedItems << item; - //prepareGeometryChange will call updateItem + //prepareGeometryChange will call prepareBoundingRectChange foreach (QGraphicsItem *child, item->children()) child->prepareGeometryChange(); } @@ -180,13 +179,15 @@ void QGraphicsSceneBspTreeIndex::prepareBoundingRectChange(const QGraphicsItem * QList QGraphicsSceneBspTreeIndex::estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const { const_cast(this)->purgeRemovedItems(); + scene()->d_func()->_q_updateSortCache(); + QList rectItems = bsp.items(rect); // Fill in with any unindexed items for (int i = 0; i < unindexedItems.size(); ++i) { if (QGraphicsItem *item = unindexedItems.at(i)) { if (!item->d_ptr->itemDiscovered && item->d_ptr->visible && !(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) { QRectF boundingRect = item->sceneBoundingRect(); - if (boundingRect.intersects(rect)) { + if (QRectF_intersects(boundingRect, rect)) { item->d_ptr->itemDiscovered = 1; rectItems << item; } @@ -328,7 +329,7 @@ void QGraphicsSceneBspTreeIndex::_q_updateIndex() if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) continue; - bsp.insertItem(item,rect); + bsp.insertItem(item, rect); // If the item ignores view transformations, update our // largest-item-counter to ensure that the view can accurately diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index fe3a68a..d0d6081 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -352,7 +352,7 @@ QList QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSe } } - d->scene->d_func()->sortItems(&items, Qt::AscendingOrder, d->scene->d_func()->sortCacheEnabled); + d->scene->d_func()->sortItems(&items, order, d->scene->d_func()->sortCacheEnabled); return items; } diff --git a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp index 0c5ebf6..eb117ab 100644 --- a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp +++ b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp @@ -395,6 +395,9 @@ void tst_QGraphicsScene::items() QGraphicsLineItem *l2 = scene.addLine(0, -5, 0, 5); QVERIFY(!l1->sceneBoundingRect().intersects(l2->sceneBoundingRect())); QVERIFY(!l2->sceneBoundingRect().intersects(l1->sceneBoundingRect())); + QList items; + items<setRect(QRectF(0, 0, 2000, 2000)); - QCOMPARE(index->rect(), QRectF(0, 0, 2000, 2000)); + scene->setSceneRect(QRectF(0, 0, 2000, 2000)); + QCOMPARE(index->indexedRect(), QRectF(0, 0, 2000, 2000)); } void tst_QGraphicsSceneIndex::customIndex_data() -- cgit v0.12 From f7741b78c90abcb272345810d55e446a7f390032 Mon Sep 17 00:00:00 2001 From: Tobias Koenig Date: Wed, 3 Jun 2009 17:40:41 +0200 Subject: Fixed typo in apidocs and extended example code --- doc/src/snippets/qxmlschemavalidator/main.cpp | 23 +++++++++++++++++++++++ src/xmlpatterns/api/qxmlschema.cpp | 5 +++++ src/xmlpatterns/api/qxmlschemavalidator.cpp | 12 +++++++++--- 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/doc/src/snippets/qxmlschemavalidator/main.cpp b/doc/src/snippets/qxmlschemavalidator/main.cpp index 13cd45f..0803380 100644 --- a/doc/src/snippets/qxmlschemavalidator/main.cpp +++ b/doc/src/snippets/qxmlschemavalidator/main.cpp @@ -48,6 +48,7 @@ class SchemaValidator void validateFromUrl() const; void validateFromFile() const; void validateFromData() const; + void validateComplete() const; private: QXmlSchema getSchema() const; @@ -123,6 +124,27 @@ QXmlSchema SchemaValidator::getSchema() const return schema; } +void SchemaValidator::validateComplete() const +{ +//! [3] + QUrl schemaUrl("file:///home/user/schema.xsd"); + + QXmlSchema schema; + schema.load(schemaUrl); + + if (schema.isValid()) { + QFile file("test.xml"); + file.open(QIODevice::ReadOnly); + + QXmlSchemaValidator validator(schema); + if (validator.validate(&file, QUrl::fromLocalFile(file.fileName()))) + qDebug() << "instance document is valid"; + else + qDebug() << "instance document is invalid"; + } +//! [3] +} + int main(int argc, char **argv) { QCoreApplication app(argc, argv); @@ -132,6 +154,7 @@ int main(int argc, char **argv) validator.validateFromUrl(); validator.validateFromFile(); validator.validateFromData(); + validator.validateComplete(); return 0; } diff --git a/src/xmlpatterns/api/qxmlschema.cpp b/src/xmlpatterns/api/qxmlschema.cpp index ec370ca..c6dc9b2 100644 --- a/src/xmlpatterns/api/qxmlschema.cpp +++ b/src/xmlpatterns/api/qxmlschema.cpp @@ -58,6 +58,11 @@ that can be used further for validation of XML instance documents via \l{QXmlSchemaValidator}. + The following example shows how to load a XML Schema file from the network + and test whether it is a valid schema document: + + \snippet doc/src/snippets/qxmlschema/main.cpp 0 + \sa QXmlSchemaValidator, {xmlpatterns/schema}{XML Schema Validation Example} */ diff --git a/src/xmlpatterns/api/qxmlschemavalidator.cpp b/src/xmlpatterns/api/qxmlschemavalidator.cpp index dc8e55d..d5596c5 100644 --- a/src/xmlpatterns/api/qxmlschemavalidator.cpp +++ b/src/xmlpatterns/api/qxmlschemavalidator.cpp @@ -63,6 +63,12 @@ The QXmlSchemaValidator class loads, parses an XML instance document and validates it against a W3C XML Schema that has been compiled with \l{QXmlSchema}. + The following example shows how to load a XML Schema from a local + file, check whether it is a valid schema document and use it for validation + of an XML instance document: + + \snippet doc/src/snippets/qxmlschemavalidator/main.cpp 3 + \sa QXmlSchema, {xmlpatterns/schema}{XML Schema Validation Example} */ @@ -110,7 +116,7 @@ void QXmlSchemaValidator::setSchema(const QXmlSchema &schema) Validates the XML instance document read from \a data with the given \a documentUri against the schema. - Returns \c true if the XML instance document is valid according the + Returns \c true if the XML instance document is valid according to the schema, \c false otherwise. Example: @@ -130,7 +136,7 @@ bool QXmlSchemaValidator::validate(const QByteArray &data, const QUrl &documentU /*! Validates the XML instance document read from \a source against the schema. - Returns \c true if the XML instance document is valid according the + Returns \c true if the XML instance document is valid according to the schema, \c false otherwise. Example: @@ -155,7 +161,7 @@ bool QXmlSchemaValidator::validate(const QUrl &source) const Validates the XML instance document read from \a source with the given \a documentUri against the schema. - Returns \c true if the XML instance document is valid according the + Returns \c true if the XML instance document is valid according to the schema, \c false otherwise. Example: -- cgit v0.12 From ffd6bc0351c96c8a3828bd7376f2b6bda317cd71 Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Wed, 3 Jun 2009 18:23:20 +0200 Subject: Remove the sorting cache from the QGraphicsScene and move it to the BSP. Now the QGraphicsScene has no idea how works the index. So we can improve it separatly, add new ones and benchmarks existing ones. --- src/gui/graphicsview/graphicsview.pri | 1 + src/gui/graphicsview/qgraphicsitem.cpp | 22 +- src/gui/graphicsview/qgraphicsitem.h | 1 + src/gui/graphicsview/qgraphicsscene.cpp | 200 +------ src/gui/graphicsview/qgraphicsscene.h | 2 +- src/gui/graphicsview/qgraphicsscene_p.h | 19 - .../graphicsview/qgraphicsscenebsptreeindex_p.cpp | 614 ++++++++++++++------- .../graphicsview/qgraphicsscenebsptreeindex_p.h | 51 +- .../graphicsview/qgraphicsscenebsptreeindex_p_p.h | 140 +++++ src/gui/graphicsview/qgraphicssceneindex.cpp | 28 +- src/gui/graphicsview/qgraphicssceneindex.h | 9 +- src/gui/graphicsview/qgraphicssceneindex_p.h | 3 +- src/gui/graphicsview/qgraphicsscenelinearindex_p.h | 2 +- src/gui/graphicsview/qgraphicsview.cpp | 11 +- tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 5 + tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp | 5 +- tests/auto/qgraphicsview/tst_qgraphicsview.cpp | 8 +- 17 files changed, 642 insertions(+), 479 deletions(-) create mode 100644 src/gui/graphicsview/qgraphicsscenebsptreeindex_p_p.h diff --git a/src/gui/graphicsview/graphicsview.pri b/src/gui/graphicsview/graphicsview.pri index cc57892..a4a79e8 100644 --- a/src/gui/graphicsview/graphicsview.pri +++ b/src/gui/graphicsview/graphicsview.pri @@ -7,6 +7,7 @@ HEADERS += \ graphicsview/qgraphicsscene.h \ graphicsview/qgraphicsscene_p.h \ graphicsview/qgraphicsscenebsptreeindex_p.h \ + graphicsview/qgraphicsscenebsptreeindex_p_p.h \ graphicsview/qgraphicsscene_bsp_p.h \ graphicsview/qgraphicsscenelinearindex_p.h \ graphicsview/qgraphicssceneindex.h \ diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index fc5895c..ee32724 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -537,6 +537,7 @@ #include "qgraphicsview.h" #include "qgraphicswidget.h" #include "qgraphicsproxywidget.h" +#include "qgraphicsscenebsptreeindex_p_p.h" #include #include #include @@ -888,12 +889,6 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, bool de } } - if (scene) { - // Invalidate any sort caching; arrival of a new item means we need to - // resort. - scene->d_func()->invalidateSortCache(); - } - // Resolve opacity. updateEffectiveOpacity(); @@ -905,6 +900,11 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, bool de // Deliver post-change notification q->itemChange(QGraphicsItem::ItemParentHasChanged, newParentVariant); + + if (scene) { + // Deliver the change to the index + scene->d_func()->index->itemChanged(q, QGraphicsItem::ItemParentHasChanged, newParentVariant); + } } /*! @@ -3528,11 +3528,9 @@ void QGraphicsItem::setZValue(qreal z) d_ptr->z = newZ; d_ptr->fullUpdateHelper(); - if (d_ptr->scene) { - // Invalidate any sort caching; arrival of a new item means we need to - // resort. - d_ptr->scene->d_func()->invalidateSortCache(); - } + //Z Value has changed, we have to notify the index. + if (d_ptr->scene) + d_ptr->scene->d_func()->index->itemChanged(this, ItemZValueChange, z); itemChange(ItemZValueHasChanged, newZVariant); } @@ -3991,7 +3989,7 @@ bool QGraphicsItem::isObscuredBy(const QGraphicsItem *item) const { if (!item) return false; - return QGraphicsScenePrivate::closestItemFirst_withoutCache(item, this) + return QGraphicsSceneBspTreeIndexPrivate::closestItemFirst_withoutCache(item, this) && qt_QGraphicsItem_isObscured(this, item, boundingRect()); } diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index e244c13..7874033 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -435,6 +435,7 @@ private: friend class QGraphicsSceneIndex; friend class QGraphicsSceneIndexPrivate; friend class QGraphicsSceneBspTreeIndex; + friend class QGraphicsSceneBspTreeIndexPrivate; friend class ::tst_QGraphicsItem; friend bool qt_closestLeaf(const QGraphicsItem *, const QGraphicsItem *); friend bool qt_closestItemFirst(const QGraphicsItem *, const QGraphicsItem *); diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 0172a23..4734e74 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -218,6 +218,7 @@ #include "qgraphicswidget.h" #include "qgraphicswidget_p.h" #include "qgraphicssceneindex.h" +#include "qgraphicsscenebsptreeindex_p_p.h" #include #include @@ -291,8 +292,6 @@ QGraphicsScenePrivate::QGraphicsScenePrivate() allItemsIgnoreHoverEvents(true), allItemsUseDefaultCursor(true), painterStateProtection(true), - sortCacheEnabled(false), - updatingSortCache(false), style(0) { } @@ -1073,175 +1072,6 @@ QGraphicsWidget *QGraphicsScenePrivate::windowForItem(const QGraphicsItem *item) return 0; } -void QGraphicsScenePrivate::invalidateSortCache() -{ - Q_Q(QGraphicsScene); - if (!sortCacheEnabled || updatingSortCache) - return; - - updatingSortCache = true; - QMetaObject::invokeMethod(q, "_q_updateSortCache", Qt::QueuedConnection); -} - -/*! - \internal - - Should not be exported, but we can't change that now. - ### Qt 5: Remove symbol / make static -*/ -inline bool qt_closestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2) -{ - // Return true if sibling item1 is on top of item2. - const QGraphicsItemPrivate *d1 = item1->d_ptr; - const QGraphicsItemPrivate *d2 = item2->d_ptr; - bool f1 = d1->flags & QGraphicsItem::ItemStacksBehindParent; - bool f2 = d2->flags & QGraphicsItem::ItemStacksBehindParent; - if (f1 != f2) return f2; - qreal z1 = d1->z; - qreal z2 = d2->z; - return z1 != z2 ? z1 > z2 : d1->siblingIndex > d2->siblingIndex; -} - -/*! - \internal - - Should not be exported, but we can't change that now. -*/ -inline bool qt_closestItemFirst(const QGraphicsItem *item1, const QGraphicsItem *item2) -{ - return QGraphicsScenePrivate::closestItemFirst_withoutCache(item1, item2); -} - -/*! - Returns true if \a item1 is on top of \a item2. - - \internal -*/ -bool QGraphicsScenePrivate::closestItemFirst_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2) -{ - // Siblings? Just check their z-values. - const QGraphicsItemPrivate *d1 = item1->d_ptr; - const QGraphicsItemPrivate *d2 = item2->d_ptr; - if (d1->parent == d2->parent) - return qt_closestLeaf(item1, item2); - - // Find common ancestor, and each item's ancestor closest to the common - // ancestor. - int item1Depth = d1->depth; - int item2Depth = d2->depth; - const QGraphicsItem *p = item1; - const QGraphicsItem *t1 = item1; - while (item1Depth > item2Depth && (p = p->d_ptr->parent)) { - if (p == item2) { - // item2 is one of item1's ancestors; item1 is on top - return !(t1->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent); - } - t1 = p; - --item1Depth; - } - p = item2; - const QGraphicsItem *t2 = item2; - while (item2Depth > item1Depth && (p = p->d_ptr->parent)) { - if (p == item1) { - // item1 is one of item2's ancestors; item1 is not on top - return (t2->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent); - } - t2 = p; - --item2Depth; - } - - // item1Ancestor is now at the same level as item2Ancestor, but not the same. - const QGraphicsItem *a1 = t1; - const QGraphicsItem *a2 = t2; - while (a1) { - const QGraphicsItem *p1 = a1; - const QGraphicsItem *p2 = a2; - a1 = a1->parentItem(); - a2 = a2->parentItem(); - if (a1 && a1 == a2) - return qt_closestLeaf(p1, p2); - } - - // No common ancestor? Then just compare the items' toplevels directly. - return qt_closestLeaf(t1->topLevelItem(), t2->topLevelItem()); -} - -/*! - Returns true if \a item2 is on top of \a item1. - - \internal -*/ -bool QGraphicsScenePrivate::closestItemLast_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2) -{ - return closestItemFirst_withoutCache(item2, item1); -} - -void QGraphicsScenePrivate::climbTree(QGraphicsItem *item, int *stackingOrder) -{ - if (!item->d_ptr->children.isEmpty()) { - QList childList = item->d_ptr->children; - qSort(childList.begin(), childList.end(), qt_closestLeaf); - for (int i = 0; i < childList.size(); ++i) { - QGraphicsItem *item = childList.at(i); - if (!(item->flags() & QGraphicsItem::ItemStacksBehindParent)) - climbTree(childList.at(i), stackingOrder); - } - item->d_ptr->globalStackingOrder = (*stackingOrder)++; - for (int i = 0; i < childList.size(); ++i) { - QGraphicsItem *item = childList.at(i); - if (item->flags() & QGraphicsItem::ItemStacksBehindParent) - climbTree(childList.at(i), stackingOrder); - } - } else { - item->d_ptr->globalStackingOrder = (*stackingOrder)++; - } -} - -void QGraphicsScenePrivate::_q_updateSortCache() -{ - //### FIXME - QGraphicsSceneBspTreeIndex *tree = qobject_cast(index); - if (tree) { - tree->_q_updateIndex(); - } - - if (!sortCacheEnabled || !updatingSortCache) - return; - - updatingSortCache = false; - int stackingOrder = 0; - - QList topLevels; - - for (int i = 0; i < index->items().count(); ++i) { - QGraphicsItem *item = index->items().at(i); - if (item && item->parentItem() == 0) - topLevels << item; - } - - qSort(topLevels.begin(), topLevels.end(), qt_closestLeaf); - for (int i = 0; i < topLevels.size(); ++i) - climbTree(topLevels.at(i), &stackingOrder); -} - -void QGraphicsScenePrivate::sortItems(QList *itemList, Qt::SortOrder order, - bool sortCacheEnabled) -{ - if (sortCacheEnabled) { - if (order == Qt::AscendingOrder) { - qSort(itemList->begin(), itemList->end(), closestItemFirst_withCache); - } else if (order == Qt::DescendingOrder) { - qSort(itemList->begin(), itemList->end(), closestItemLast_withCache); - } - } else { - if (order == Qt::AscendingOrder) { - qSort(itemList->begin(), itemList->end(), closestItemFirst_withoutCache); - } else if (order == Qt::DescendingOrder) { - qSort(itemList->begin(), itemList->end(), closestItemLast_withoutCache); - } - } -} - /*! \internal @@ -1707,15 +1537,25 @@ void QGraphicsScene::setBspTreeDepth(int depth) bool QGraphicsScene::isSortCacheEnabled() const { Q_D(const QGraphicsScene); - return d->sortCacheEnabled; + QGraphicsSceneBspTreeIndex *bspTree = qobject_cast(d->index); + if (!bspTree) { + qWarning("QGraphicsScene::isSortCacheEnabled: can not apply if indexing method is not BSP"); + return false; + } + return bspTree->d_func()->sortCacheEnabled; } void QGraphicsScene::setSortCacheEnabled(bool enabled) { Q_D(QGraphicsScene); - if (enabled == d->sortCacheEnabled) + QGraphicsSceneBspTreeIndex *bspTree = qobject_cast(d->index); + if (!bspTree) { + qWarning("QGraphicsScene::isSortCacheEnabled: can not apply if indexing method is not BSP"); return; - if ((d->sortCacheEnabled = enabled)) - d->invalidateSortCache(); + } + if (enabled == bspTree->d_func()->sortCacheEnabled) + return; + if ((bspTree->d_func()->sortCacheEnabled = enabled)) + bspTree->d_func()->invalidateSortCache(); } /*! @@ -1910,8 +1750,6 @@ QList QGraphicsScene::collidingItems(const QGraphicsItem *item, if (item != itemInVicinity && item->collidesWithItem(itemInVicinity, mode)) tmp << itemInVicinity; } - //### remove me - d->sortItems(&tmp, Qt::AscendingOrder, d->sortCacheEnabled); return tmp; } @@ -2211,10 +2049,6 @@ void QGraphicsScene::addItem(QGraphicsItem *item) return; } - // Invalidate any sort caching; arrival of a new item means we need to - // resort. - d->invalidateSortCache(); - // Detach this item from its parent if the parent's scene is different // from this scene. if (QGraphicsItem *itemParent = item->parentItem()) { @@ -2232,10 +2066,6 @@ void QGraphicsScene::addItem(QGraphicsItem *item) if (!item->d_ptr->parent) d->registerTopLevelItem(item); - // Update the scene's sort cache settings. - item->d_ptr->globalStackingOrder = -1; - d->invalidateSortCache(); - // Add to list of items that require an update. We cannot assume that the // item is fully constructed, so calling item->update() can lead to a pure // virtual function call to boundingRect(). diff --git a/src/gui/graphicsview/qgraphicsscene.h b/src/gui/graphicsview/qgraphicsscene.h index 5d70087..702813c 100644 --- a/src/gui/graphicsview/qgraphicsscene.h +++ b/src/gui/graphicsview/qgraphicsscene.h @@ -290,7 +290,6 @@ private: Q_PRIVATE_SLOT(d_func(), void _q_removeItemLater(QGraphicsItem *item)) Q_PRIVATE_SLOT(d_func(), void _q_updateLater()) Q_PRIVATE_SLOT(d_func(), void _q_polishItems()) - Q_PRIVATE_SLOT(d_func(), void _q_updateSortCache()) Q_PRIVATE_SLOT(d_func(), void _q_resetDirtyItems()) friend class QGraphicsItem; friend class QGraphicsItemPrivate; @@ -301,6 +300,7 @@ private: friend class QGraphicsSceneIndex; friend class QGraphicsSceneIndexPrivate; friend class QGraphicsSceneBspTreeIndex; + friend class QGraphicsSceneBspTreeIndexPrivate; }; Q_DECLARE_OPERATORS_FOR_FLAGS(QGraphicsScene::SceneLayers) diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index a035159..d2a5cdb 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -187,25 +187,6 @@ public: void sendMouseEvent(QGraphicsSceneMouseEvent *mouseEvent); void mousePressEventHandler(QGraphicsSceneMouseEvent *mouseEvent); QGraphicsWidget *windowForItem(const QGraphicsItem *item) const; - bool sortCacheEnabled; - bool updatingSortCache; - void invalidateSortCache(); - static void climbTree(QGraphicsItem *item, int *stackingOrder); - void _q_updateSortCache(); - - static bool closestItemFirst_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2); - static bool closestItemLast_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2); - - static inline bool closestItemFirst_withCache(const QGraphicsItem *item1, const QGraphicsItem *item2) - { - return item1->d_ptr->globalStackingOrder < item2->d_ptr->globalStackingOrder; - } - static inline bool closestItemLast_withCache(const QGraphicsItem *item1, const QGraphicsItem *item2) - { - return item1->d_ptr->globalStackingOrder >= item2->d_ptr->globalStackingOrder; - } - - static void sortItems(QList *itemList, Qt::SortOrder order, bool cached); void drawItemHelper(QGraphicsItem *item, QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget, diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp index f8f1f56..19aa9d5 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp @@ -39,9 +39,15 @@ ** ****************************************************************************/ + static const int QGRAPHICSSCENE_INDEXTIMER_TIMEOUT = 2000; #include "qgraphicsscenebsptreeindex_p.h" + +#ifndef QT_NO_GRAPHICSVIEW + +#include "qgraphicsscenebsptreeindex_p_p.h" +#include "qgraphicssceneindex_p.h" #include "qgraphicsitem_p.h" #include "qgraphicsscene_p.h" @@ -49,51 +55,365 @@ static const int QGRAPHICSSCENE_INDEXTIMER_TIMEOUT = 2000; #include -QGraphicsSceneBspTreeIndex::QGraphicsSceneBspTreeIndex(QGraphicsScene *scene) - : QGraphicsSceneIndex(scene), +QT_BEGIN_NAMESPACE + +static inline int intmaxlog(int n) +{ + return (n > 0 ? qMax(qCeil(qLn(qreal(n)) / qLn(qreal(2))), 5) : 0); +} + +/*! + Constructs a private scene index. +*/ +QGraphicsSceneBspTreeIndexPrivate::QGraphicsSceneBspTreeIndexPrivate(QGraphicsScene *scene) + : scene(scene), bspTreeDepth(0), indexTimerId(0), restartIndexTimer(false), regenerateIndex(true), lastItemCount(0), - purgePending(false) + purgePending(false), + sortCacheEnabled(false), + updatingSortCache(false) +{ +} + + +/*! + \internal +*/ +void QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex() { + Q_Q(QGraphicsSceneBspTreeIndex); + if (!indexTimerId) + return; + QGraphicsScenePrivate * scenePrivate = q->scene()->d_func(); + q->killTimer(indexTimerId); + indexTimerId = 0; + + purgeRemovedItems(); + + // Add unindexedItems to indexedItems + QRectF unindexedItemsBoundingRect; + for (int i = 0; i < unindexedItems.size(); ++i) { + if (QGraphicsItem *item = unindexedItems.at(i)) { + unindexedItemsBoundingRect |= item->sceneBoundingRect(); + if (!freeItemIndexes.isEmpty()) { + int freeIndex = freeItemIndexes.takeFirst(); + item->d_func()->index = freeIndex; + indexedItems[freeIndex] = item; + } else { + item->d_func()->index = indexedItems.size(); + indexedItems << item; + } + } + } + + // Update growing scene rect. + QRectF oldGrowingItemsBoundingRect = scenePrivate->growingItemsBoundingRect; + scenePrivate->growingItemsBoundingRect |= unindexedItemsBoundingRect; + + // Determine whether we should regenerate the BSP tree. + if (bspTreeDepth == 0) { + int oldDepth = intmaxlog(lastItemCount); + bspTreeDepth = intmaxlog(indexedItems.size()); + static const int slack = 100; + if (bsp.leafCount() == 0 || (oldDepth != bspTreeDepth && qAbs(lastItemCount - indexedItems.size()) > slack)) { + // ### Crude algorithm. + regenerateIndex = true; + } + } + + // Regenerate the tree. + if (regenerateIndex) { + regenerateIndex = false; + bsp.initialize(q->scene()->sceneRect(), bspTreeDepth); + unindexedItems = indexedItems; + lastItemCount = indexedItems.size(); + q->scene()->update(); + + // Take this opportunity to reset our largest-item counter for + // untransformable items. When the items are inserted into the BSP + // tree, we'll get an accurate calculation. + scenePrivate->largestUntransformableItem = QRectF(); + } + + // Insert all unindexed items into the tree. + for (int i = 0; i < unindexedItems.size(); ++i) { + if (QGraphicsItem *item = unindexedItems.at(i)) { + QRectF rect = item->sceneBoundingRect(); + if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) + continue; + + bsp.insertItem(item, rect); + + // If the item ignores view transformations, update our + // largest-item-counter to ensure that the view can accurately + // discover untransformable items when drawing. + if (item->d_ptr->itemIsUntransformable()) { + QGraphicsItem *topmostUntransformable = item; + while (topmostUntransformable && (topmostUntransformable->d_ptr->ancestorFlags + & QGraphicsItemPrivate::AncestorIgnoresTransformations)) { + topmostUntransformable = topmostUntransformable->parentItem(); + } + // ### Verify that this is the correct largest untransformable rectangle. + scenePrivate->largestUntransformableItem |= item->mapToItem(topmostUntransformable, item->boundingRect()).boundingRect(); + } + } + } + unindexedItems.clear(); + + // Notify scene rect changes. + if (!scenePrivate->hasSceneRect && scenePrivate->growingItemsBoundingRect != oldGrowingItemsBoundingRect) + emit q->scene()->sceneRectChanged(scenePrivate->growingItemsBoundingRect); } -QRectF QGraphicsSceneBspTreeIndex::indexedRect() + +/*! + \internal + + Removes stale pointers from all data structures. +*/ +void QGraphicsSceneBspTreeIndexPrivate::purgeRemovedItems() +{ + Q_Q(QGraphicsSceneBspTreeIndex); + if (!purgePending && removedItems.isEmpty()) + return; + + // Remove stale items from the BSP tree. + bsp.removeItems(removedItems.toSet()); + // Purge this list. + removedItems.clear(); + freeItemIndexes.clear(); + for (int i = 0; i < indexedItems.size(); ++i) { + if (!indexedItems.at(i)) + freeItemIndexes << i; + } + purgePending = false; + + // No locality info for the items; update the whole scene. + q->scene()->update(); +} + +/*! + \internal + + Starts or restarts the timer used for reindexing unindexed items. +*/ +void QGraphicsSceneBspTreeIndexPrivate::startIndexTimer() +{ + Q_Q(QGraphicsSceneBspTreeIndex); + if (indexTimerId) { + restartIndexTimer = true; + } else { + indexTimerId = q->startTimer(QGRAPHICSSCENE_INDEXTIMER_TIMEOUT); + } +} + +/*! + \internal +*/ +void QGraphicsSceneBspTreeIndexPrivate::resetIndex() +{ + purgeRemovedItems(); + for (int i = 0; i < indexedItems.size(); ++i) { + if (QGraphicsItem *item = indexedItems.at(i)) { + item->d_ptr->index = -1; + unindexedItems << item; + } + } + indexedItems.clear(); + freeItemIndexes.clear(); + regenerateIndex = true; + startIndexTimer(); +} + +void QGraphicsSceneBspTreeIndexPrivate::climbTree(QGraphicsItem *item, int *stackingOrder) { + if (!item->d_ptr->children.isEmpty()) { + QList childList = item->d_ptr->children; + qSort(childList.begin(), childList.end(), qt_closestLeaf); + for (int i = 0; i < childList.size(); ++i) { + QGraphicsItem *item = childList.at(i); + if (!(item->flags() & QGraphicsItem::ItemStacksBehindParent)) + climbTree(childList.at(i), stackingOrder); + } + item->d_ptr->globalStackingOrder = (*stackingOrder)++; + for (int i = 0; i < childList.size(); ++i) { + QGraphicsItem *item = childList.at(i); + if (item->flags() & QGraphicsItem::ItemStacksBehindParent) + climbTree(childList.at(i), stackingOrder); + } + } else { + item->d_ptr->globalStackingOrder = (*stackingOrder)++; + } +} + +void QGraphicsSceneBspTreeIndexPrivate::_q_updateSortCache() +{ + Q_Q(QGraphicsSceneBspTreeIndex); _q_updateIndex(); + + if (!sortCacheEnabled || !updatingSortCache) + return; + + updatingSortCache = false; + int stackingOrder = 0; + + QList topLevels; + + for (int i = 0; i < q->items().count(); ++i) { + QGraphicsItem *item = q->items().at(i); + if (item && item->parentItem() == 0) + topLevels << item; + } + + qSort(topLevels.begin(), topLevels.end(), qt_closestLeaf); + for (int i = 0; i < topLevels.size(); ++i) + climbTree(topLevels.at(i), &stackingOrder); +} + +void QGraphicsSceneBspTreeIndexPrivate::invalidateSortCache() +{ + Q_Q(QGraphicsSceneBspTreeIndex); + if (!sortCacheEnabled || updatingSortCache) + return; + + updatingSortCache = true; + QMetaObject::invokeMethod(q, "_q_updateSortCache", Qt::QueuedConnection); +} + +/*! + Returns true if \a item1 is on top of \a item2. + + \internal +*/ +bool QGraphicsSceneBspTreeIndexPrivate::closestItemFirst_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2) +{ + // Siblings? Just check their z-values. + const QGraphicsItemPrivate *d1 = item1->d_ptr; + const QGraphicsItemPrivate *d2 = item2->d_ptr; + if (d1->parent == d2->parent) + return qt_closestLeaf(item1, item2); + + // Find common ancestor, and each item's ancestor closest to the common + // ancestor. + int item1Depth = d1->depth; + int item2Depth = d2->depth; + const QGraphicsItem *p = item1; + const QGraphicsItem *t1 = item1; + while (item1Depth > item2Depth && (p = p->d_ptr->parent)) { + if (p == item2) { + // item2 is one of item1's ancestors; item1 is on top + return !(t1->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent); + } + t1 = p; + --item1Depth; + } + p = item2; + const QGraphicsItem *t2 = item2; + while (item2Depth > item1Depth && (p = p->d_ptr->parent)) { + if (p == item1) { + // item1 is one of item2's ancestors; item1 is not on top + return (t2->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent); + } + t2 = p; + --item2Depth; + } + + // item1Ancestor is now at the same level as item2Ancestor, but not the same. + const QGraphicsItem *a1 = t1; + const QGraphicsItem *a2 = t2; + while (a1) { + const QGraphicsItem *p1 = a1; + const QGraphicsItem *p2 = a2; + a1 = a1->parentItem(); + a2 = a2->parentItem(); + if (a1 && a1 == a2) + return qt_closestLeaf(p1, p2); + } + + // No common ancestor? Then just compare the items' toplevels directly. + return qt_closestLeaf(t1->topLevelItem(), t2->topLevelItem()); +} + +/*! + Returns true if \a item2 is on top of \a item1. + + \internal +*/ +bool QGraphicsSceneBspTreeIndexPrivate::closestItemLast_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2) +{ + return closestItemFirst_withoutCache(item2, item1); +} + +void QGraphicsSceneBspTreeIndexPrivate::sortItems(QList *itemList, Qt::SortOrder order, + bool sortCacheEnabled) +{ + if (sortCacheEnabled) { + if (order == Qt::AscendingOrder) { + qSort(itemList->begin(), itemList->end(), closestItemFirst_withCache); + } else if (order == Qt::DescendingOrder) { + qSort(itemList->begin(), itemList->end(), closestItemLast_withCache); + } + } else { + if (order == Qt::AscendingOrder) { + qSort(itemList->begin(), itemList->end(), closestItemFirst_withoutCache); + } else if (order == Qt::DescendingOrder) { + qSort(itemList->begin(), itemList->end(), closestItemLast_withoutCache); + } + } +} + +QGraphicsSceneBspTreeIndex::QGraphicsSceneBspTreeIndex(QGraphicsScene *scene) + : QGraphicsSceneIndex(*new QGraphicsSceneBspTreeIndexPrivate(scene), scene) +{ + +} + +QRectF QGraphicsSceneBspTreeIndex::indexedRect() const +{ + Q_D(const QGraphicsSceneBspTreeIndex); + const_cast(d)->_q_updateIndex(); return scene()->d_func()->hasSceneRect ? scene()->d_func()->sceneRect : scene()->d_func()->growingItemsBoundingRect; } void QGraphicsSceneBspTreeIndex::clear() { - bsp.clear(); - lastItemCount = 0; - freeItemIndexes.clear(); - m_indexedItems.clear(); - unindexedItems.clear(); + Q_D(QGraphicsSceneBspTreeIndex); + d->bsp.clear(); + d->lastItemCount = 0; + d->freeItemIndexes.clear(); + d->indexedItems.clear(); + d->unindexedItems.clear(); } void QGraphicsSceneBspTreeIndex::addItem(QGraphicsItem *item) { + Q_D(QGraphicsSceneBspTreeIndex); // Prevent reusing a recently deleted pointer: purge all removed items // from our lists. - purgeRemovedItems(); + d->purgeRemovedItems(); + + // Invalidate any sort caching; arrival of a new item means we need to + // resort. + // Update the scene's sort cache settings. + item->d_ptr->globalStackingOrder = -1; + d->invalidateSortCache(); // Indexing requires sceneBoundingRect(), but because \a item might // not be completely constructed at this point, we need to store it in // a temporary list and schedule an indexing for later. - unindexedItems << item; + d->unindexedItems << item; item->d_func()->index = -1; - startIndexTimer(); + d->startIndexTimer(); } /*! \internal */ -void QGraphicsSceneBspTreeIndex::addToIndex(QGraphicsItem *item) +void QGraphicsSceneBspTreeIndexPrivate::addToIndex(QGraphicsItem *item) { if (item->d_func()->index != -1) { bsp.insertItem(item, item->sceneBoundingRect()); @@ -109,37 +429,47 @@ void QGraphicsSceneBspTreeIndex::addToIndex(QGraphicsItem *item) void QGraphicsSceneBspTreeIndex::removeItem(QGraphicsItem *item) { + Q_D(QGraphicsSceneBspTreeIndex); // Note: This will access item's sceneBoundingRect(), which (as this is // C++) is why we cannot call removeItem() from QGraphicsItem's // destructor. - removeFromIndex(item); + d->removeFromIndex(item); + + // Invalidate any sort caching; arrival of a new item means we need to + // resort. + d->invalidateSortCache(); // Remove from our item lists. int index = item->d_func()->index; if (index != -1) { - freeItemIndexes << index; - m_indexedItems[index] = 0; + d->freeItemIndexes << index; + d->indexedItems[index] = 0; } else { - unindexedItems.removeAll(item); + d->unindexedItems.removeAll(item); } } void QGraphicsSceneBspTreeIndex::deleteItem(QGraphicsItem *item) { + Q_D(QGraphicsSceneBspTreeIndex); + // Invalidate any sort caching; arrival of a new item means we need to + // resort. + d->invalidateSortCache(); + int index = item->d_func()->index; if (index != -1) { // Important: The index is useless until purgeRemovedItems() is // called. - m_indexedItems[index] = (QGraphicsItem *)0; - if (!purgePending) { - purgePending = true; + d->indexedItems[index] = (QGraphicsItem *)0; + if (!d->purgePending) { + d->purgePending = true; scene()->update(); } - removedItems << item; + d->removedItems << item; } else { // Recently added items are purged immediately. unindexedItems() never // contains stale items. - unindexedItems.removeAll(item); + d->unindexedItems.removeAll(item); scene()->update(); } } @@ -147,7 +477,7 @@ void QGraphicsSceneBspTreeIndex::deleteItem(QGraphicsItem *item) /*! \internal */ -void QGraphicsSceneBspTreeIndex::removeFromIndex(QGraphicsItem *item) +void QGraphicsSceneBspTreeIndexPrivate::removeFromIndex(QGraphicsItem *item) { if (item->d_func()->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) { // ### remove from child index only if applicable @@ -157,7 +487,7 @@ void QGraphicsSceneBspTreeIndex::removeFromIndex(QGraphicsItem *item) if (index != -1) { bsp.removeItem(item, item->sceneBoundingRect()); freeItemIndexes << index; - m_indexedItems[index] = 0; + indexedItems[index] = 0; item->d_func()->index = -1; unindexedItems << item; @@ -170,21 +500,23 @@ void QGraphicsSceneBspTreeIndex::removeFromIndex(QGraphicsItem *item) void QGraphicsSceneBspTreeIndex::prepareBoundingRectChange(const QGraphicsItem *item) { + Q_D(QGraphicsSceneBspTreeIndex); // Note: This will access item's sceneBoundingRect(), which (as this is // C++) is why we cannot call removeItem() from QGraphicsItem's // destructor. - removeFromIndex(const_cast(item)); + d->removeFromIndex(const_cast(item)); } QList QGraphicsSceneBspTreeIndex::estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const { - const_cast(this)->purgeRemovedItems(); - scene()->d_func()->_q_updateSortCache(); + Q_D(const QGraphicsSceneBspTreeIndex); + const_cast(d)->purgeRemovedItems(); + const_cast(d)->_q_updateSortCache(); - QList rectItems = bsp.items(rect); + QList rectItems = d->bsp.items(rect); // Fill in with any unindexed items - for (int i = 0; i < unindexedItems.size(); ++i) { - if (QGraphicsItem *item = unindexedItems.at(i)) { + for (int i = 0; i < d->unindexedItems.size(); ++i) { + if (QGraphicsItem *item = d->unindexedItems.at(i)) { if (!item->d_ptr->itemDiscovered && item->d_ptr->visible && !(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) { QRectF boundingRect = item->sceneBoundingRect(); if (QRectF_intersects(boundingRect, rect)) { @@ -199,57 +531,83 @@ QList QGraphicsSceneBspTreeIndex::estimateItems(const QRectF &r for (int i = 0; i < rectItems.size(); ++i) rectItems.at(i)->d_func()->itemDiscovered = 0; + d->sortItems(&rectItems, order, d->sortCacheEnabled); + return rectItems; } -QList QGraphicsSceneBspTreeIndex::items() const +QList QGraphicsSceneBspTreeIndex::items(Qt::SortOrder order) const { - const_cast(this)->purgeRemovedItems(); + Q_D(const QGraphicsSceneBspTreeIndex); + const_cast(d)->purgeRemovedItems(); + QList itemList; // If freeItemIndexes is empty, we know there are no holes in indexedItems and // unindexedItems. - if (freeItemIndexes.isEmpty()) { - if (unindexedItems.isEmpty()) - return m_indexedItems; - return m_indexedItems + unindexedItems; - } - - // Rebuild the list of items to avoid holes. ### We could also just - // compress the item lists at this point. - QList itemList; - foreach (QGraphicsItem *item, m_indexedItems + unindexedItems) { - if (item) - itemList << item; + if (d->freeItemIndexes.isEmpty()) { + if (d->unindexedItems.isEmpty()) { + itemList = d->indexedItems; + } else { + itemList = d->indexedItems + d->unindexedItems; + } + } else { + // Rebuild the list of items to avoid holes. ### We could also just + // compress the item lists at this point. + foreach (QGraphicsItem *item, d->indexedItems + d->unindexedItems) { + if (item) + itemList << item; + } } + //We sort descending order + d->sortItems(&itemList, order, d->sortCacheEnabled); return itemList; } int QGraphicsSceneBspTreeIndex::bspDepth() { - return bspTreeDepth; + Q_D(const QGraphicsSceneBspTreeIndex); + return d->bspTreeDepth; } void QGraphicsSceneBspTreeIndex::setBspDepth(int depth) { - bspTreeDepth = depth; - resetIndex(); + Q_D(QGraphicsSceneBspTreeIndex); + d->bspTreeDepth = depth; + d->resetIndex(); } void QGraphicsSceneBspTreeIndex::sceneRectChanged(const QRectF &rect) { - m_sceneRect = rect; - resetIndex(); + Q_D(QGraphicsSceneBspTreeIndex); + d->sceneRect = rect; + d->resetIndex(); +} + +void QGraphicsSceneBspTreeIndex::itemChanged(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value) +{ + Q_D(QGraphicsSceneBspTreeIndex); + switch (change) { + case QGraphicsItem::ItemZValueChange: + case QGraphicsItem::ItemParentChange: { + d->invalidateSortCache(); + break; + } + default: + break; + } + return QGraphicsSceneIndex::itemChanged(item, change, value); } bool QGraphicsSceneBspTreeIndex::event(QEvent *event) { + Q_D(QGraphicsSceneBspTreeIndex); switch (event->type()) { case QEvent::Timer: - if (indexTimerId && static_cast(event)->timerId() == indexTimerId) { - if (restartIndexTimer) { - restartIndexTimer = false; + if (d->indexTimerId && static_cast(event)->timerId() == d->indexTimerId) { + if (d->restartIndexTimer) { + d->restartIndexTimer = false; } else { // this call will kill the timer - _q_updateIndex(); + d->_q_updateIndex(); } } // Fallthrough intended - support timers in subclasses. @@ -259,153 +617,9 @@ bool QGraphicsSceneBspTreeIndex::event(QEvent *event) return true; } -static inline int intmaxlog(int n) -{ - return (n > 0 ? qMax(qCeil(qLn(qreal(n)) / qLn(qreal(2))), 5) : 0); -} +QT_END_NAMESPACE -/*! - \internal -*/ -void QGraphicsSceneBspTreeIndex::_q_updateIndex() -{ - if (!indexTimerId) - return; +#include "moc_qgraphicsscenebsptreeindex_p.cpp" - killTimer(indexTimerId); - indexTimerId = 0; +#endif // QT_NO_GRAPHICSVIEW - purgeRemovedItems(); - - // Add unindexedItems to indexedItems - QRectF unindexedItemsBoundingRect; - for (int i = 0; i < unindexedItems.size(); ++i) { - if (QGraphicsItem *item = unindexedItems.at(i)) { - unindexedItemsBoundingRect |= item->sceneBoundingRect(); - if (!freeItemIndexes.isEmpty()) { - int freeIndex = freeItemIndexes.takeFirst(); - item->d_func()->index = freeIndex; - m_indexedItems[freeIndex] = item; - } else { - item->d_func()->index = m_indexedItems.size(); - m_indexedItems << item; - } - } - } - - // Update growing scene rect. - QRectF oldGrowingItemsBoundingRect = scene()->d_func()->growingItemsBoundingRect; - scene()->d_func()->growingItemsBoundingRect |= unindexedItemsBoundingRect; - - // Determine whether we should regenerate the BSP tree. - if (bspTreeDepth == 0) { - int oldDepth = intmaxlog(lastItemCount); - bspTreeDepth = intmaxlog(m_indexedItems.size()); - static const int slack = 100; - if (bsp.leafCount() == 0 || (oldDepth != bspTreeDepth && qAbs(lastItemCount - m_indexedItems.size()) > slack)) { - // ### Crude algorithm. - regenerateIndex = true; - } - } - - // Regenerate the tree. - if (regenerateIndex) { - regenerateIndex = false; - bsp.initialize(scene()->sceneRect(), bspTreeDepth); - unindexedItems = m_indexedItems; - lastItemCount = m_indexedItems.size(); - scene()->update(); - - // Take this opportunity to reset our largest-item counter for - // untransformable items. When the items are inserted into the BSP - // tree, we'll get an accurate calculation. - scene()->d_func()->largestUntransformableItem = QRectF(); - } - - // Insert all unindexed items into the tree. - for (int i = 0; i < unindexedItems.size(); ++i) { - if (QGraphicsItem *item = unindexedItems.at(i)) { - QRectF rect = item->sceneBoundingRect(); - if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) - continue; - - bsp.insertItem(item, rect); - - // If the item ignores view transformations, update our - // largest-item-counter to ensure that the view can accurately - // discover untransformable items when drawing. - if (item->d_ptr->itemIsUntransformable()) { - QGraphicsItem *topmostUntransformable = item; - while (topmostUntransformable && (topmostUntransformable->d_ptr->ancestorFlags - & QGraphicsItemPrivate::AncestorIgnoresTransformations)) { - topmostUntransformable = topmostUntransformable->parentItem(); - } - // ### Verify that this is the correct largest untransformable rectangle. - scene()->d_func()->largestUntransformableItem |= item->mapToItem(topmostUntransformable, item->boundingRect()).boundingRect(); - } - } - } - unindexedItems.clear(); - - // Notify scene rect changes. - if (!scene()->d_func()->hasSceneRect && scene()->d_func()->growingItemsBoundingRect != oldGrowingItemsBoundingRect) - emit scene()->sceneRectChanged(scene()->d_func()->growingItemsBoundingRect); -} - - -/*! - \internal - - Removes stale pointers from all data structures. -*/ -void QGraphicsSceneBspTreeIndex::purgeRemovedItems() -{ - if (!purgePending && removedItems.isEmpty()) - return; - - // Remove stale items from the BSP tree. - bsp.removeItems(removedItems.toSet()); - // Purge this list. - removedItems.clear(); - freeItemIndexes.clear(); - for (int i = 0; i < m_indexedItems.size(); ++i) { - if (!m_indexedItems.at(i)) - freeItemIndexes << i; - } - purgePending = false; - - // No locality info for the items; update the whole scene. - scene()->update(); -} - -/*! - \internal - - Starts or restarts the timer used for reindexing unindexed items. -*/ -void QGraphicsSceneBspTreeIndex::startIndexTimer() -{ - if (indexTimerId) { - restartIndexTimer = true; - } else { - indexTimerId = startTimer(QGRAPHICSSCENE_INDEXTIMER_TIMEOUT); - } -} - -/*! - \internal -*/ -void QGraphicsSceneBspTreeIndex::resetIndex() -{ - purgeRemovedItems(); - for (int i = 0; i < m_indexedItems.size(); ++i) { - if (QGraphicsItem *item = m_indexedItems.at(i)) { - item->d_ptr->index = -1; - unindexedItems << item; - } - } - m_indexedItems.clear(); - freeItemIndexes.clear(); - regenerateIndex = true; - startIndexTimer(); -} diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h index 7a6ea0b..b1ea977 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h @@ -56,56 +56,41 @@ QT_BEGIN_NAMESPACE #include "qgraphicsscene_bsp_p.h" +class QGraphicsSceneBspTreeIndexPrivate; class Q_AUTOTEST_EXPORT QGraphicsSceneBspTreeIndex : public QGraphicsSceneIndex { Q_OBJECT public: QGraphicsSceneBspTreeIndex(QGraphicsScene *scene = 0); - QRectF indexedRect(); - - void clear(); - - void addItem(QGraphicsItem *item); - void removeItem(QGraphicsItem *item); - void deleteItem(QGraphicsItem *item); - void prepareBoundingRectChange(const QGraphicsItem *item); + QRectF indexedRect() const; QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const; - QList items() const; + QList items(Qt::SortOrder order = Qt::AscendingOrder) const; int bspDepth(); void setBspDepth(int depth); protected: bool event(QEvent *event); - void sceneRectChanged(const QRectF &rect); + void clear(); + + void addItem(QGraphicsItem *item); + void removeItem(QGraphicsItem *item); + void deleteItem(QGraphicsItem *item); + void prepareBoundingRectChange(const QGraphicsItem *item); -public slots : - void _q_updateIndex(); + void sceneRectChanged(const QRectF &rect); + void itemChanged(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value); private : - QGraphicsSceneBspTree bsp; - QRectF m_sceneRect; - int bspTreeDepth; - int indexTimerId; - bool restartIndexTimer; - bool regenerateIndex; - int lastItemCount; - - QList m_indexedItems; - QList unindexedItems; - QList freeItemIndexes; - - bool purgePending; - QList removedItems; - void purgeRemovedItems(); - - void startIndexTimer(); - void resetIndex(); - - void addToIndex(QGraphicsItem *item); - void removeFromIndex(QGraphicsItem *item); + Q_DECLARE_PRIVATE(QGraphicsSceneBspTreeIndex) + Q_DISABLE_COPY(QGraphicsSceneBspTreeIndex) + Q_PRIVATE_SLOT(d_func(), void _q_updateSortCache()) + Q_PRIVATE_SLOT(d_func(), void _q_updateIndex()) + + friend class QGraphicsScene; + friend class QGraphicsScenePrivate; }; QT_END_NAMESPACE diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p_p.h new file mode 100644 index 0000000..2df5fbc --- /dev/null +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p_p.h @@ -0,0 +1,140 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGRAPHICSSCENEBSPTREEINDEX_P_P_H +#define QGRAPHICSSCENEBSPTREEINDEX_P_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header +// file may change from version to version without notice, or even be removed. +// +// We mean it. +// + +#include "qgraphicsscenebsptreeindex_p.h" + +#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW + +#include +#include + +QT_BEGIN_NAMESPACE + +class QGraphicsScene; + +class QGraphicsSceneBspTreeIndexPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QGraphicsSceneBspTreeIndex) +public: + QGraphicsSceneBspTreeIndexPrivate(QGraphicsScene *scene); + + QGraphicsScene *scene; + QGraphicsSceneBspTree bsp; + QRectF sceneRect; + int bspTreeDepth; + int indexTimerId; + bool restartIndexTimer; + bool regenerateIndex; + int lastItemCount; + + QList indexedItems; + QList unindexedItems; + QList freeItemIndexes; + + bool purgePending; + QList removedItems; + void purgeRemovedItems(); + + void _q_updateIndex(); + void startIndexTimer(); + void resetIndex(); + + void addToIndex(QGraphicsItem *item); + void removeFromIndex(QGraphicsItem *item); + + void _q_updateSortCache(); + bool sortCacheEnabled; + bool updatingSortCache; + void invalidateSortCache(); + + static void climbTree(QGraphicsItem *item, int *stackingOrder); + static bool closestItemFirst_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2); + static bool closestItemLast_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2); + + static inline bool closestItemFirst_withCache(const QGraphicsItem *item1, const QGraphicsItem *item2) + { + return item1->d_ptr->globalStackingOrder < item2->d_ptr->globalStackingOrder; + } + static inline bool closestItemLast_withCache(const QGraphicsItem *item1, const QGraphicsItem *item2) + { + return item1->d_ptr->globalStackingOrder >= item2->d_ptr->globalStackingOrder; + } + + static void sortItems(QList *itemList, Qt::SortOrder order, bool cached); +}; + + +/*! + \internal +*/ +inline bool qt_closestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2) +{ + // Return true if sibling item1 is on top of item2. + const QGraphicsItemPrivate *d1 = item1->d_ptr; + const QGraphicsItemPrivate *d2 = item2->d_ptr; + bool f1 = d1->flags & QGraphicsItem::ItemStacksBehindParent; + bool f2 = d2->flags & QGraphicsItem::ItemStacksBehindParent; + if (f1 != f2) return f2; + qreal z1 = d1->z; + qreal z2 = d2->z; + return z1 != z2 ? z1 > z2 : d1->siblingIndex > d2->siblingIndex; +} + +QT_END_NAMESPACE + +#endif // QGRAPHICSSCENEBSPTREEINDEX_P_P_H + +#endif + diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index d0d6081..eeee74e 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -41,6 +41,7 @@ #include "qgraphicssceneindex.h" #include "qgraphicssceneindex_p.h" +#include "qgraphicsscenebsptreeindex_p_p.h" #include "qgraphicsscene.h" #include "qgraphicsitem_p.h" #include "qgraphicsscene_p.h" @@ -282,6 +283,14 @@ QGraphicsSceneIndex::QGraphicsSceneIndex(QGraphicsScene *scene) } /*! + \internal +*/ +QGraphicsSceneIndex::QGraphicsSceneIndex(QObjectPrivate &dd, QGraphicsScene *scene) + : QObject(dd, scene) +{ +} + +/*! Destroys the scene index. */ QGraphicsSceneIndex::~QGraphicsSceneIndex() @@ -301,7 +310,7 @@ QGraphicsScene* QGraphicsSceneIndex::scene() const /*! Returns the indexed area for the index */ -QRectF QGraphicsSceneIndex::indexedRect() +QRectF QGraphicsSceneIndex::indexedRect() const { Q_D(const QGraphicsSceneIndex); return d->scene->d_func()->sceneRect; @@ -351,8 +360,9 @@ QList QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSe d->childItems_helper(&items, item, xinv.map(pos)); } } - - d->scene->d_func()->sortItems(&items, order, d->scene->d_func()->sortCacheEnabled); + //### Needed but it should be handle differently + if (order != Qt::SortOrder(-1)) + QGraphicsSceneBspTreeIndexPrivate::sortItems(&items, order, false); return items; } @@ -415,9 +425,9 @@ QList QGraphicsSceneIndex::items(const QRectF &rect, Qt::ItemSe } } } - + //### Needed but it should be handle differently if (order != Qt::SortOrder(-1)) - d->scene->d_func()->sortItems(&items, order, d->scene->d_func()->sortCacheEnabled); + QGraphicsSceneBspTreeIndexPrivate::sortItems(&items, order, false); return items; } @@ -474,9 +484,9 @@ QList QGraphicsSceneIndex::items(const QPolygonF &polygon, Qt:: d->childItems_helper(&items, item, xinv.map(polygon), mode); } } - + //### Needed but it should be handle differently if (order != Qt::SortOrder(-1)) - d->scene->d_func()->sortItems(&items, order, d->scene->d_func()->sortCacheEnabled); + QGraphicsSceneBspTreeIndexPrivate::sortItems(&items, order, false); return items; } QList QGraphicsSceneIndex::items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const @@ -525,9 +535,9 @@ QList QGraphicsSceneIndex::items(const QPainterPath &path, Qt:: d->childItems_helper(&items, item, xinv.map(path), mode); } } - + //### Needed but it should be handle differently if (order != Qt::SortOrder(-1)) - d->scene->d_func()->sortItems(&items, order, d->scene->d_func()->sortCacheEnabled); + QGraphicsSceneBspTreeIndexPrivate::sortItems(&items, order, false); return items; } diff --git a/src/gui/graphicsview/qgraphicssceneindex.h b/src/gui/graphicsview/qgraphicssceneindex.h index 11d9aae..084a623 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.h +++ b/src/gui/graphicsview/qgraphicssceneindex.h @@ -71,9 +71,9 @@ public: QGraphicsScene *scene() const; - virtual QRectF indexedRect(); + virtual QRectF indexedRect() const; - virtual QList items() const = 0; + virtual QList items(Qt::SortOrder order = Qt::AscendingOrder) const = 0; virtual QList items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; virtual QList items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; virtual QList items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; @@ -91,10 +91,15 @@ protected: virtual void prepareBoundingRectChange(const QGraphicsItem *item); virtual void sceneRectChanged(const QRectF &rect); + QGraphicsSceneIndex(QObjectPrivate &dd, QGraphicsScene *scene); + friend class QGraphicsScene; friend class QGraphicsScenePrivate; friend class QGraphicsItem; + friend class QGraphicsItemPrivate; + friend class QGraphicsSceneBspTreeIndex; private: + Q_DISABLE_COPY(QGraphicsSceneIndex) Q_DECLARE_PRIVATE(QGraphicsSceneIndex) }; diff --git a/src/gui/graphicsview/qgraphicssceneindex_p.h b/src/gui/graphicsview/qgraphicssceneindex_p.h index f2cdca3..2014693 100644 --- a/src/gui/graphicsview/qgraphicssceneindex_p.h +++ b/src/gui/graphicsview/qgraphicssceneindex_p.h @@ -58,6 +58,7 @@ #if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW #include +#include QT_BEGIN_NAMESPACE @@ -86,7 +87,7 @@ public: const QPainterPath &path, Qt::ItemSelectionMode mode) const; - QGraphicsScene *scene; + QGraphicsScene *scene; }; QT_END_NAMESPACE diff --git a/src/gui/graphicsview/qgraphicsscenelinearindex_p.h b/src/gui/graphicsview/qgraphicsscenelinearindex_p.h index dc45a17..3057b4a 100644 --- a/src/gui/graphicsview/qgraphicsscenelinearindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenelinearindex_p.h @@ -105,7 +105,7 @@ public: return result; } - QList items() const { + QList items(Qt::SortOrder order = Qt::AscendingOrder) const { return m_items; } }; diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 91f97a1..e8330a9 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -1056,7 +1056,7 @@ QList QGraphicsViewPrivate::findItems(const QRegion &exposedReg *allItems = true; // All items are guaranteed within the exposed region, don't bother using the index. - QList itemList(scene->items()); + QList itemList(scene->d_func()->index->items(Qt::DescendingOrder)); int i = 0; while (i < itemList.size()) { const QGraphicsItem *item = itemList.at(i); @@ -1069,9 +1069,6 @@ QList QGraphicsViewPrivate::findItems(const QRegion &exposedReg else ++i; } - - // Sort the items. - QGraphicsScenePrivate::sortItems(&itemList, Qt::DescendingOrder, scene->d_func()->sortCacheEnabled); return itemList; } @@ -2134,7 +2131,7 @@ QList QGraphicsViewPrivate::itemsInArea(const QPainterPath &pat // Then find the minimal list of items that are inside \a path, and // convert it to a set. - QList regularCandidates = scene->items(q->mapToScene(path), mode); + QList regularCandidates = scene->items(q->mapToScene(path), mode, order, q->transform()); QSet candSet = QSet::fromList(regularCandidates); QTransform viewMatrix = q->viewportTransform(); @@ -2161,10 +2158,6 @@ QList QGraphicsViewPrivate::itemsInArea(const QPainterPath &pat } ++it; } - - // ### Insertion sort would be faster. - if (order != Qt::SortOrder(-1)) - QGraphicsScenePrivate::sortItems(&result, order, scene->d_func()->sortCacheEnabled); return result; } diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index 8afdeb4..c83134f 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -4685,6 +4685,11 @@ void tst_QGraphicsItem::itemClipsChildrenToShape() scene.render(&painter); painter.end(); + QGraphicsView view(&scene); + view.show(); + + QTest::qWait(5000); + QCOMPARE(image.pixel(16, 16), QColor(255, 0, 0).rgba()); QCOMPARE(image.pixel(32, 32), QColor(0, 0, 255).rgba()); QCOMPARE(image.pixel(50, 50), QColor(0, 255, 0).rgba()); diff --git a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp index eb117ab..dd997c7 100644 --- a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp +++ b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp @@ -379,8 +379,7 @@ void tst_QGraphicsScene::items() for (int x = minX; x < maxX; x += 100) items << scene.addRect(QRectF(0, 0, 10, 10)); } - - QCOMPARE(scene.items(), items); + QCOMPARE(scene.items().size(), items.size()); scene.itemAt(0, 0); // trigger indexing scene.removeItem(items.at(5)); @@ -397,7 +396,7 @@ void tst_QGraphicsScene::items() QVERIFY(!l2->sceneBoundingRect().intersects(l1->sceneBoundingRect())); QList items; items<rect().center()); - QTest::qWait(100); + QTest::qWait(250); for (int size = 200; size <= 400; size += 25) { view.resize(size, size); @@ -2122,7 +2122,7 @@ void tst_QGraphicsView::resizeAnchor() QVERIFY(qAbs(newCenter.x() - center.x()) < slack); QVERIFY(qAbs(newCenter.y() - center.y()) < slack); } - QTest::qWait(100); + QTest::qWait(250); } } } @@ -2925,7 +2925,7 @@ void tst_QGraphicsView::task245469_itemsAtPointWithClip() QTest::qWait(100); QList itemsAtCenter = view.items(view.viewport()->rect().center()); - QCOMPARE(itemsAtCenter, (QList() << child << parent)); + QCOMPARE(itemsAtCenter, (QList() << parent << child)); QPolygonF p = view.mapToScene(QRect(view.viewport()->rect().center(), QSize(1, 1))); QList itemsAtCenter2 = scene.items(p); -- cgit v0.12 From cea8678e5fca8b33bbd5da057282888bc260a5c9 Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Thu, 4 Jun 2009 16:46:36 +0200 Subject: Fix doc and auto-test regression. --- src/gui/graphicsview/qgraphicsscene.cpp | 2 +- tests/auto/qgraphicsview/tst_qgraphicsview.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 4734e74..d811ade 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -1586,7 +1586,7 @@ QList QGraphicsScene::items() const /*! Returns all visible items at position \a pos in the scene. The items are - listed in descending Z order (i.e., the first item in the list is the + listed in descending stacking order (i.e., the first item in the list is the top-most item, and the last item is the bottom-most item). \sa itemAt() diff --git a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp index 447de34..696a42d 100644 --- a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp +++ b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp @@ -2925,7 +2925,7 @@ void tst_QGraphicsView::task245469_itemsAtPointWithClip() QTest::qWait(100); QList itemsAtCenter = view.items(view.viewport()->rect().center()); - QCOMPARE(itemsAtCenter, (QList() << parent << child)); + QCOMPARE(itemsAtCenter, (QList() << child << parent)); QPolygonF p = view.mapToScene(QRect(view.viewport()->rect().center(), QSize(1, 1))); QList itemsAtCenter2 = scene.items(p); -- cgit v0.12 From 3d9d7d10c2c6a4aed4650572bc9f3c8bd5b899b5 Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Thu, 11 Jun 2009 17:05:32 +0200 Subject: Kill one items_helper + one childItem helper and use the new recursive approach. --- src/gui/graphicsview/qgraphicsscene.cpp | 5 +- src/gui/graphicsview/qgraphicssceneindex.cpp | 232 ++++++++++++--------------- src/gui/graphicsview/qgraphicssceneindex_p.h | 7 +- 3 files changed, 110 insertions(+), 134 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 33232af..0a1cd2b 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -1734,10 +1734,7 @@ QList QGraphicsScene::items(const QPointF &pos) const QList QGraphicsScene::items(const QRectF &rect, Qt::ItemSelectionMode mode) const { Q_D(const QGraphicsScene); - QList itemList; - //###d->index->items(rect, mode, Qt::AscendingOrder); - d->recursive_items_helper(0, rect, &itemList, QTransform(), QTransform(), mode, Qt::AscendingOrder); - return itemList; + return d->index->items(rect, mode, Qt::AscendingOrder); } /*! diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index 6895911..954cef3 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -57,57 +57,121 @@ QGraphicsSceneIndexPrivate::QGraphicsSceneIndexPrivate(QGraphicsScene *scene) : { } -void QGraphicsSceneIndexPrivate::childItems_helper(QList *items, - const QGraphicsItem *parent, - const QPointF &pos) const +void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRectF rect, + QList *items, + const QTransform &parentTransform, + const QTransform &viewTransform, + Qt::ItemSelectionMode mode, Qt::SortOrder order, + qreal parentOpacity) const { - bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape); - if (parentClip && parent->d_ptr->isClippedAway()) - return; - // ### is this needed? - if (parentClip && !parent->boundingRect().contains(pos)) - return; + // Calculate opacity. + qreal opacity; + if (item) { + if (!item->d_ptr->visible) + return; + QGraphicsItem *p = item->d_ptr->parent; + bool itemIgnoresParentOpacity = item->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity; + bool parentDoesntPropagateOpacity = (p && (p->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)); + if (!itemIgnoresParentOpacity && !parentDoesntPropagateOpacity) { + opacity = parentOpacity * item->opacity(); + } else { + opacity = item->d_ptr->opacity; + } + if (opacity == 0.0 && !(item->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) + return; + } else { + opacity = parentOpacity; + } - QList &children = parent->d_ptr->children; - for (int i = 0; i < children.size(); ++i) { - QGraphicsItem *item = children.at(i); - if (item->d_ptr->transformData && !item->d_ptr->transformData->computedFullTransform().isInvertible()) - continue; + // Calculate the full transform for this item. + QTransform transform = parentTransform; + bool keep = false; + if (item) { + item->d_ptr->combineTransformFromParent(&transform, &viewTransform); + + // ### This does not take the clip into account. + QRectF brect = item->boundingRect(); + _q_adjustRect(&brect); + + keep = true; + if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect) + keep = rect.contains(transform.mapRect(brect)) && rect != brect; + else + keep = rect.intersects(transform.mapRect(brect)); + + if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { + QPainterPath rectPath; + rectPath.addRect(rect); + keep = scene->d_func()->itemCollidesWithPath(item, transform.inverted().map(rectPath), mode); + } + } - // Skip invisible items and all their children. - if (item->d_ptr->isInvisible()) - continue; + bool childClip = (item && (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)); + bool dontProcessItem = !item || !keep; + bool dontProcessChildren = item && dontProcessItem && childClip; + + // Find and sort children. + QList &children = item ? item->d_ptr->children : const_cast(scene->d_func())->topLevelItems; + if (!dontProcessChildren) { + if (item && item->d_ptr->needSortChildren) { + item->d_ptr->needSortChildren = 0; + qStableSort(children.begin(), children.end(), qt_notclosestLeaf); + } else if (!item && scene->d_func()->needSortTopLevelItems) { + const_cast(scene->d_func())->needSortTopLevelItems = false; + qStableSort(children.begin(), children.end(), qt_notclosestLeaf); + } + } - bool keep = false; - if (!item->d_ptr->isClippedAway()) { - if (item->contains(item->mapFromParent(pos))) { - items->append(item); - keep = true; - } + childClip &= !dontProcessChildren & !children.isEmpty(); + + // Clip. + if (childClip) + rect &= transform.map(item->shape()).controlPointRect(); + + // Process children behind + int i = 0; + if (!dontProcessChildren) { + for (i = 0; i < children.size(); ++i) { + QGraphicsItem *child = children.at(i); + if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent)) + break; + recursive_items_helper(child, rect, items, transform, viewTransform, + mode, order, opacity); } + } - if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) - // Recurse into children. - childItems_helper(items, item, item->mapFromParent(pos)); + // Process item + if (!dontProcessItem) + items->append(item); + + // Process children in front + if (!dontProcessChildren) { + for (; i < children.size(); ++i) + recursive_items_helper(children.at(i), rect, items, transform, viewTransform, + mode, order, opacity); } -} + if (!item && order == Qt::AscendingOrder) { + int n = items->size(); + for (int i = 0; i < n / 2; ++i) { + QGraphicsItem *tmp = (*items)[n - i - 1]; + (*items)[n - i - 1] = (*items)[i]; + (*items)[i] = tmp; + } + } +} void QGraphicsSceneIndexPrivate::childItems_helper(QList *items, const QGraphicsItem *parent, - const QRectF &rect, - Qt::ItemSelectionMode mode) const + const QPointF &pos) const { bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape); if (parentClip && parent->d_ptr->isClippedAway()) return; - QRectF adjustedRect(rect); - _q_adjustRect(&adjustedRect); - QRectF r = !parentClip ? adjustedRect : adjustedRect.intersected(adjustedItemBoundingRect(parent)); - if (r.isEmpty()) + // ### is this needed? + if (parentClip && !parent->boundingRect().contains(pos)) return; - QPainterPath path; QList &children = parent->d_ptr->children; for (int i = 0; i < children.size(); ++i) { QGraphicsItem *item = children.at(i); @@ -120,45 +184,18 @@ void QGraphicsSceneIndexPrivate::childItems_helper(QList *items bool keep = false; if (!item->d_ptr->isClippedAway()) { - // ### _q_adjustedRect is only needed because QRectF::intersects, - // QRectF::contains and QTransform::map() and friends don't work with - // flat rectangles. - const QRectF br(adjustedItemBoundingRect(item)); - QRectF mbr = item->mapRectToParent(br); - if (mode >= Qt::ContainsItemBoundingRect) { - // Rect intersects/contains item's bounding rect - if ((mode == Qt::IntersectsItemBoundingRect && QRectF_intersects(rect, mbr)) - || (mode == Qt::ContainsItemBoundingRect && rect != mbr && rect.contains(br))) { - items->append(item); - keep = true; - } - } else { - // Rect intersects/contains item's shape - if (QRectF_intersects(rect, mbr)) { - if (path == QPainterPath()) - path.addRect(rect); - if (scene->d_func()->itemCollidesWithPath(item, item->mapFromParent(path), mode)) { - items->append(item); - keep = true; - } - } + if (item->contains(item->mapFromParent(pos))) { + items->append(item); + keep = true; } } - if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) { + if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) // Recurse into children. - if (!item->d_ptr->transformData || item->d_ptr->transformData->computedFullTransform().type() <= QTransform::TxScale) { - // Rect - childItems_helper(items, item, item->mapRectFromParent(rect), mode); - } else { - // Polygon - childItems_helper(items, item, item->mapFromParent(rect), mode); - } - } + childItems_helper(items, item, item->mapFromParent(pos)); } } - void QGraphicsSceneIndexPrivate::childItems_helper(QList *items, const QGraphicsItem *parent, const QPolygonF &polygon, @@ -369,66 +406,9 @@ QList QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSe QList QGraphicsSceneIndex::items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const { Q_D(const QGraphicsSceneIndex); - QList items; - - QPainterPath path; - - // The index returns a rough estimate of what items are inside the rect. - // Refine it by iterating through all returned items. - QRectF adjustedRect(rect); - _q_adjustRect(&adjustedRect); - foreach (QGraphicsItem *item, estimateItems(adjustedRect, order, deviceTransform)) { - // Find the item's scene transform in a clever way. - QTransform x = item->sceneTransform(); - bool keep = false; - - // ### _q_adjustedRect is only needed because QRectF::intersects, - // QRectF::contains and QTransform::map() and friends don't work with - // flat rectangles. - const QRectF br(adjustedItemBoundingRect(item)); - if (mode >= Qt::ContainsItemBoundingRect) { - // Rect intersects/contains item's bounding rect - QRectF mbr = x.mapRect(br); - if ((mode == Qt::IntersectsItemBoundingRect && QRectF_intersects(rect, mbr)) - || (mode == Qt::ContainsItemBoundingRect && rect != mbr && rect.contains(mbr))) { - items << item; - keep = true; - } - } else { - // Rect intersects/contains item's shape - if (QRectF_intersects(adjustedRect, x.mapRect(br))) { - bool ok; - QTransform xinv = x.inverted(&ok); - if (ok) { - if (path.isEmpty()) - path.addRect(rect); - if (d->scene->d_func()->itemCollidesWithPath(item, xinv.map(path), mode)) { - items << item; - keep = true; - } - } - } - } - - if (keep && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) { - // Recurse into children that clip children. - bool ok; - QTransform xinv = x.inverted(&ok); - if (ok) { - if (x.type() <= QTransform::TxScale) { - // Rect - d->childItems_helper(&items, item, xinv.mapRect(rect), mode); - } else { - // Polygon - d->childItems_helper(&items, item, xinv.map(rect), mode); - } - } - } - } - //### Needed but it should be handle differently - if (order != Qt::SortOrder(-1)) - QGraphicsSceneBspTreeIndexPrivate::sortItems(&items, order, false); - return items; + QList itemList; + d->recursive_items_helper(0, rect, &itemList, QTransform(), deviceTransform, mode, order); + return itemList; } QList QGraphicsSceneIndex::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const diff --git a/src/gui/graphicsview/qgraphicssceneindex_p.h b/src/gui/graphicsview/qgraphicssceneindex_p.h index 2014693..3a2cb27 100644 --- a/src/gui/graphicsview/qgraphicssceneindex_p.h +++ b/src/gui/graphicsview/qgraphicssceneindex_p.h @@ -70,16 +70,15 @@ class QGraphicsSceneIndexPrivate : public QObjectPrivate public: QGraphicsSceneIndexPrivate(QGraphicsScene *scene); + void recursive_items_helper(QGraphicsItem *item, QRectF rect, QList *items, + const QTransform &parentTransform, const QTransform &viewTransform, + Qt::ItemSelectionMode mode, Qt::SortOrder order, qreal parentOpacity = 1.0) const; void childItems_helper(QList *items, const QGraphicsItem *parent, const QPointF &pos) const; void childItems_helper(QList *items, const QGraphicsItem *parent, - const QRectF &rect, - Qt::ItemSelectionMode mode) const; - void childItems_helper(QList *items, - const QGraphicsItem *parent, const QPolygonF &polygon, Qt::ItemSelectionMode mode) const; void childItems_helper(QList *items, -- cgit v0.12 From da70cf2876cee57299dbeebb86c4c3881e3df721 Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Mon, 15 Jun 2009 20:50:26 +0200 Subject: Kill items_helper and child_items_helper for ever. We have now on function recusrsive_item_helper that doing the job. To resolve different use cases we use concept of interceptors for QRectF, QPointF QPolygonF and QPainterPath. --- src/gui/graphicsview/qgraphicsscene.cpp | 5 + src/gui/graphicsview/qgraphicsscene_p.h | 2 + .../graphicsview/qgraphicsscenebsptreeindex_p.cpp | 3 +- .../graphicsview/qgraphicsscenebsptreeindex_p_p.h | 5 +- src/gui/graphicsview/qgraphicssceneindex.cpp | 408 ++++++--------------- src/gui/graphicsview/qgraphicssceneindex_p.h | 36 +- 6 files changed, 140 insertions(+), 319 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 0a1cd2b..eb06186 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -312,6 +312,11 @@ void QGraphicsScenePrivate::init() q->update(); } +QGraphicsScenePrivate *QGraphicsScenePrivate::get(QGraphicsScene *q) +{ + return q->d_func(); +} + void QGraphicsScenePrivate::_q_emitUpdated() { Q_Q(QGraphicsScene); diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index afdba7e..c63e121 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -85,6 +85,8 @@ public: QGraphicsScenePrivate(); void init(); + static QGraphicsScenePrivate *get(QGraphicsScene *q); + quint32 changedSignalMask; QGraphicsScene::ItemIndexMethod indexMethod; diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp index 97d0500..acadcbd 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp @@ -64,7 +64,7 @@ static inline int intmaxlog(int n) Constructs a private scene index. */ QGraphicsSceneBspTreeIndexPrivate::QGraphicsSceneBspTreeIndexPrivate(QGraphicsScene *scene) - : scene(scene), + : QGraphicsSceneIndexPrivate(scene), bspTreeDepth(0), indexTimerId(0), restartIndexTimer(false), @@ -175,7 +175,6 @@ void QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex() */ void QGraphicsSceneBspTreeIndexPrivate::purgeRemovedItems() { - Q_Q(QGraphicsSceneBspTreeIndex); if (!purgePending && removedItems.isEmpty()) return; diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p_p.h index 098b278..30f6e26 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p_p.h +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p_p.h @@ -57,7 +57,7 @@ #if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW -#include +#include #include QT_BEGIN_NAMESPACE @@ -66,13 +66,12 @@ static const int QGRAPHICSSCENE_INDEXTIMER_TIMEOUT = 2000; class QGraphicsScene; -class QGraphicsSceneBspTreeIndexPrivate : public QObjectPrivate +class QGraphicsSceneBspTreeIndexPrivate : public QGraphicsSceneIndexPrivate { Q_DECLARE_PUBLIC(QGraphicsSceneBspTreeIndex) public: QGraphicsSceneBspTreeIndexPrivate(QGraphicsScene *scene); - QGraphicsScene *scene; QGraphicsSceneBspTree bsp; QRectF sceneRect; int bspTreeDepth; diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index 954cef3..8d18806 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -50,14 +50,88 @@ QT_BEGIN_NAMESPACE +class QGraphicsSceneIndexRectIntersector : public QGraphicsSceneIndexIntersector +{ +public: + QGraphicsSceneIndexRectIntersector(QGraphicsScene *scene) : QGraphicsSceneIndexIntersector(scene) {} + bool intersect(const QRectF &brect) const + { + bool keep = true; + if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect) + keep = rect.contains(transform.mapRect(brect)) && rect != brect; + else + keep = rect.intersects(transform.mapRect(brect)); + + if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { + QPainterPath rectPath; + rectPath.addRect(rect); + keep = QGraphicsScenePrivate::get(scene)->itemCollidesWithPath(item, transform.inverted().map(rectPath), mode); + } + return keep; + } +}; + +class QGraphicsSceneIndexPointIntersector : public QGraphicsSceneIndexIntersector +{ +public: + QGraphicsSceneIndexPointIntersector(QGraphicsScene *scene) : QGraphicsSceneIndexIntersector(scene) {} + bool intersect(const QRectF &brect) const + { + bool keep = false; + if (rect.intersects(transform.mapRect(brect))) + if (item->contains(transform.inverted().map(pos))) + keep = true; + if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { + QPainterPath rectPath; + rectPath.addRect(rect); + keep = QGraphicsScenePrivate::get(scene)->itemCollidesWithPath(item, transform.inverted().map(rectPath), mode); + } + return keep; + } + QPointF pos; +}; + +class QGraphicsSceneIndexPathIntersector : public QGraphicsSceneIndexIntersector +{ +public: + QGraphicsSceneIndexPathIntersector(QGraphicsScene *scene) : QGraphicsSceneIndexIntersector(scene) {} + bool intersect(const QRectF &brect) const + { + bool keep = true; + if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect) + keep = rect.contains(transform.mapRect(brect)) && rect != brect; + else + keep = rect.intersects(transform.mapRect(brect)); + + if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { + keep = QGraphicsScenePrivate::get(scene)->itemCollidesWithPath(item, transform.inverted().map(path), mode); + } + return keep; + } + QPainterPath path; +}; + /*! Constructs a private scene index. */ QGraphicsSceneIndexPrivate::QGraphicsSceneIndexPrivate(QGraphicsScene *scene) : scene(scene) { + pointIntersector = new QGraphicsSceneIndexPointIntersector(scene); + rectIntersector = new QGraphicsSceneIndexRectIntersector(scene); + pathIntersector = new QGraphicsSceneIndexPathIntersector(scene); +} + +/*! + Destructor of private scene index. +*/ +QGraphicsSceneIndexPrivate::~QGraphicsSceneIndexPrivate() +{ + delete pointIntersector; + delete rectIntersector; + delete pathIntersector; } -void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRectF rect, +void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QGraphicsSceneIndexIntersector *intersector, QList *items, const QTransform &parentTransform, const QTransform &viewTransform, @@ -93,17 +167,10 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRe QRectF brect = item->boundingRect(); _q_adjustRect(&brect); - keep = true; - if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect) - keep = rect.contains(transform.mapRect(brect)) && rect != brect; - else - keep = rect.intersects(transform.mapRect(brect)); - - if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { - QPainterPath rectPath; - rectPath.addRect(rect); - keep = scene->d_func()->itemCollidesWithPath(item, transform.inverted().map(rectPath), mode); - } + //We fill the intersector with needed informations + intersector->transform = transform; + intersector->item = item; + keep = intersector->intersect(brect); } bool childClip = (item && (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)); @@ -126,7 +193,7 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRe // Clip. if (childClip) - rect &= transform.map(item->shape()).controlPointRect(); + intersector->rect &= transform.map(item->shape()).controlPointRect(); // Process children behind int i = 0; @@ -135,7 +202,7 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRe QGraphicsItem *child = children.at(i); if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent)) break; - recursive_items_helper(child, rect, items, transform, viewTransform, + recursive_items_helper(child, intersector, items, transform, viewTransform, mode, order, opacity); } } @@ -147,7 +214,7 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRe // Process children in front if (!dontProcessChildren) { for (; i < children.size(); ++i) - recursive_items_helper(children.at(i), rect, items, transform, viewTransform, + recursive_items_helper(children.at(i), intersector, items, transform, viewTransform, mode, order, opacity); } @@ -161,156 +228,6 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRe } } -void QGraphicsSceneIndexPrivate::childItems_helper(QList *items, - const QGraphicsItem *parent, - const QPointF &pos) const -{ - bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape); - if (parentClip && parent->d_ptr->isClippedAway()) - return; - // ### is this needed? - if (parentClip && !parent->boundingRect().contains(pos)) - return; - - QList &children = parent->d_ptr->children; - for (int i = 0; i < children.size(); ++i) { - QGraphicsItem *item = children.at(i); - if (item->d_ptr->transformData && !item->d_ptr->transformData->computedFullTransform().isInvertible()) - continue; - - // Skip invisible items and all their children. - if (item->d_ptr->isInvisible()) - continue; - - bool keep = false; - if (!item->d_ptr->isClippedAway()) { - if (item->contains(item->mapFromParent(pos))) { - items->append(item); - keep = true; - } - } - - if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) - // Recurse into children. - childItems_helper(items, item, item->mapFromParent(pos)); - } -} - -void QGraphicsSceneIndexPrivate::childItems_helper(QList *items, - const QGraphicsItem *parent, - const QPolygonF &polygon, - Qt::ItemSelectionMode mode) const -{ - bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape); - if (parentClip && parent->d_ptr->isClippedAway()) - return; - QRectF polyRect(polygon.boundingRect()); - _q_adjustRect(&polyRect); - QRectF r = !parentClip ? polyRect : polyRect.intersected(adjustedItemBoundingRect(parent)); - if (r.isEmpty()) - return; - - QPainterPath path; - QList &children = parent->d_ptr->children; - for (int i = 0; i < children.size(); ++i) { - QGraphicsItem *item = children.at(i); - if (item->d_ptr->transformData && !item->d_ptr->transformData->computedFullTransform().isInvertible()) - continue; - - // Skip invisible items. - if (item->d_ptr->isInvisible()) - continue; - - bool keep = false; - if (!item->d_ptr->isClippedAway()) { - // ### _q_adjustedRect is only needed because QRectF::intersects, - // QRectF::contains and QTransform::map() and friends don't work with - // flat rectangles. - const QRectF br(adjustedItemBoundingRect(item)); - if (mode >= Qt::ContainsItemBoundingRect) { - // Polygon contains/intersects item's bounding rect - if (path == QPainterPath()) - path.addPolygon(polygon); - if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(item->mapRectToParent(br))) - || (mode == Qt::ContainsItemBoundingRect && path.contains(item->mapRectToParent(br)))) { - items->append(item); - keep = true; - } - } else { - // Polygon contains/intersects item's shape - if (QRectF_intersects(polyRect, item->mapRectToParent(br))) { - if (path == QPainterPath()) - path.addPolygon(polygon); - if (scene->d_func()->itemCollidesWithPath(item, item->mapFromParent(path), mode)) { - items->append(item); - keep = true; - } - } - } - } - - if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) { - // Recurse into children that clip children. - childItems_helper(items, item, item->mapFromParent(polygon), mode); - } - } -} - -void QGraphicsSceneIndexPrivate::childItems_helper(QList *items, - const QGraphicsItem *parent, - const QPainterPath &path, - Qt::ItemSelectionMode mode) const -{ - bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape); - if (parentClip && parent->d_ptr->isClippedAway()) - return; - QRectF pathRect(path.boundingRect()); - _q_adjustRect(&pathRect); - QRectF r = !parentClip ? pathRect : pathRect.intersected(adjustedItemBoundingRect(parent)); - if (r.isEmpty()) - return; - - QList &children = parent->d_ptr->children; - for (int i = 0; i < children.size(); ++i) { - QGraphicsItem *item = children.at(i); - if (item->d_ptr->transformData && !item->d_ptr->transformData->computedFullTransform().isInvertible()) - continue; - - // Skip invisible items. - if (item->d_ptr->isInvisible()) - continue; - - bool keep = false; - if (!item->d_ptr->isClippedAway()) { - // ### _q_adjustedRect is only needed because QRectF::intersects, - // QRectF::contains and QTransform::map() and friends don't work with - // flat rectangles. - const QRectF br(adjustedItemBoundingRect(item)); - if (mode >= Qt::ContainsItemBoundingRect) { - // Polygon contains/intersects item's bounding rect - if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(item->mapRectToParent(br))) - || (mode == Qt::ContainsItemBoundingRect && path.contains(item->mapRectToParent(br)))) { - items->append(item); - keep = true; - } - } else { - // Path contains/intersects item's shape - if (QRectF_intersects(pathRect, item->mapRectToParent(br))) { - if (scene->d_func()->itemCollidesWithPath(item, item->mapFromParent(path), mode)) { - items->append(item); - keep = true; - } - } - } - } - - if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) { - // Recurse into children that clip children. - childItems_helper(items, item, item->mapFromParent(path), mode); - } - } -} - /*! Constructs an abstract scene index. */ @@ -363,162 +280,50 @@ QRectF QGraphicsSceneIndex::indexedRect() const QList QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const { Q_D(const QGraphicsSceneIndex); - QList items; - - // The index returns a rough estimate of what items are inside the rect. - // Refine it by iterating through all returned items. - QRectF adjustedRect = QRectF(pos, QSize(1,1)); - foreach (QGraphicsItem *item, estimateItems(adjustedRect, order, deviceTransform)) { - // Find the item's scene transform in a clever way. - QTransform x = item->sceneTransform(); - bool keep = false; - - // ### _q_adjustedRect is only needed because QRectF::intersects, - // QRectF::contains and QTransform::map() and friends don't work with - // flat rectangles. - const QRectF br(adjustedItemBoundingRect(item)); - // Rect intersects/contains item's shape - if (QRectF_intersects(adjustedRect, x.mapRect(br))) { - bool ok; - QTransform xinv = x.inverted(&ok); - if (ok) { - if (item->contains(xinv.map(pos))) { - items << item; - keep = true; - } - } - } - - if (keep && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) { - // Recurse into children that clip children. - bool ok; - QTransform xinv = x.inverted(&ok); - if (ok) - d->childItems_helper(&items, item, xinv.map(pos)); - } - } - //### Needed but it should be handle differently - if (order != Qt::SortOrder(-1)) - QGraphicsSceneBspTreeIndexPrivate::sortItems(&items, order, false); - return items; + QList itemList; + d->pointIntersector->mode = mode; + d->pointIntersector->rect = QRectF(pos, QSize(1,1)); + d->pointIntersector->pos = pos; + d->recursive_items_helper(0, d->pointIntersector, &itemList, QTransform(), deviceTransform, mode, order); + return itemList; } QList QGraphicsSceneIndex::items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const { Q_D(const QGraphicsSceneIndex); QList itemList; - d->recursive_items_helper(0, rect, &itemList, QTransform(), deviceTransform, mode, order); + d->rectIntersector->mode = mode; + d->rectIntersector->rect = rect; + d->recursive_items_helper(0, d->rectIntersector, &itemList, QTransform(), deviceTransform, mode, order); return itemList; } QList QGraphicsSceneIndex::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const { Q_D(const QGraphicsSceneIndex); - QList items; - + QList itemList; QRectF polyRect(polygon.boundingRect()); _q_adjustRect(&polyRect); + d->pathIntersector->mode = mode; + d->pathIntersector->rect = polyRect; QPainterPath path; - - // The index returns a rough estimate of what items are inside the rect. - // Refine it by iterating through all returned items. - foreach (QGraphicsItem *item, estimateItems(polyRect, order, deviceTransform)) { - // Find the item's scene transform in a clever way. - QTransform x = item->sceneTransform(); - bool keep = false; - - // ### _q_adjustedRect is only needed because QRectF::intersects, - // QRectF::contains and QTransform::map() and friends don't work with - // flat rectangles. - const QRectF br(adjustedItemBoundingRect(item)); - if (mode >= Qt::ContainsItemBoundingRect) { - // Polygon contains/intersects item's bounding rect - if (path == QPainterPath()) - path.addPolygon(polygon); - if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(x.mapRect(br))) - || (mode == Qt::ContainsItemBoundingRect && path.contains(x.mapRect(br)))) { - items << item; - keep = true; - } - } else { - // Polygon contains/intersects item's shape - if (QRectF_intersects(polyRect, x.mapRect(br))) { - bool ok; - QTransform xinv = x.inverted(&ok); - if (ok) { - if (path == QPainterPath()) - path.addPolygon(polygon); - if (d->scene->d_func()->itemCollidesWithPath(item, xinv.map(path), mode)) { - items << item; - keep = true; - } - } - } - } - - if (keep && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) { - // Recurse into children that clip children. - bool ok; - QTransform xinv = x.inverted(&ok); - if (ok) - d->childItems_helper(&items, item, xinv.map(polygon), mode); - } - } - //### Needed but it should be handle differently - if (order != Qt::SortOrder(-1)) - QGraphicsSceneBspTreeIndexPrivate::sortItems(&items, order, false); - return items; + path.addPolygon(polygon); + d->pathIntersector->path = path; + d->recursive_items_helper(0, d->pathIntersector, &itemList, QTransform(), deviceTransform, mode, order); + return itemList; } + QList QGraphicsSceneIndex::items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const { Q_D(const QGraphicsSceneIndex); - QList items; + QList itemList; QRectF pathRect(path.controlPointRect()); _q_adjustRect(&pathRect); - - // The index returns a rough estimate of what items are inside the rect. - // Refine it by iterating through all returned items. - foreach (QGraphicsItem *item, estimateItems(pathRect, order, deviceTransform)) { - // Find the item's scene transform in a clever way. - QTransform x = item->sceneTransform(); - bool keep = false; - - // ### _q_adjustedRect is only needed because QRectF::intersects, - // QRectF::contains and QTransform::map() and friends don't work with - // flat rectangles. - const QRectF br(adjustedItemBoundingRect(item)); - if (mode >= Qt::ContainsItemBoundingRect) { - // Path contains/intersects item's bounding rect - if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(x.mapRect(br))) - || (mode == Qt::ContainsItemBoundingRect && path.contains(x.mapRect(br)))) { - items << item; - keep = true; - } - } else { - // Path contains/intersects item's shape - if (QRectF_intersects(pathRect, x.mapRect(br))) { - bool ok; - QTransform xinv = x.inverted(&ok); - if (ok) { - if (d->scene->d_func()->itemCollidesWithPath(item, xinv.map(path), mode)) { - items << item; - keep = true; - } - } - } - } - - if (keep && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) { - bool ok; - QTransform xinv = x.inverted(&ok); - if (ok) - d->childItems_helper(&items, item, xinv.map(path), mode); - } - } - //### Needed but it should be handle differently - if (order != Qt::SortOrder(-1)) - QGraphicsSceneBspTreeIndexPrivate::sortItems(&items, order, false); - return items; + d->pathIntersector->mode = mode; + d->pathIntersector->rect = pathRect; + d->pathIntersector->path = path; + d->recursive_items_helper(0, d->pathIntersector, &itemList, QTransform(), deviceTransform, mode, order); + return itemList; } /*! @@ -592,6 +397,8 @@ void QGraphicsSceneIndex::deleteItem(QGraphicsItem *item) */ void QGraphicsSceneIndex::itemChanged(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange, const QVariant &value) { + //Q_UNUSED(item); + //Q_UNUSED(value); } /*! @@ -601,6 +408,7 @@ void QGraphicsSceneIndex::itemChanged(const QGraphicsItem *item, QGraphicsItem:: */ void QGraphicsSceneIndex::prepareBoundingRectChange(const QGraphicsItem *item) { + //Q_UNUSED(item); } /*! diff --git a/src/gui/graphicsview/qgraphicssceneindex_p.h b/src/gui/graphicsview/qgraphicssceneindex_p.h index 3a2cb27..d0d181b 100644 --- a/src/gui/graphicsview/qgraphicssceneindex_p.h +++ b/src/gui/graphicsview/qgraphicssceneindex_p.h @@ -63,30 +63,38 @@ QT_BEGIN_NAMESPACE class QGraphicsScene; +class QGraphicsSceneIndexIntersector; +class QGraphicsSceneIndexRectIntersector; +class QGraphicsSceneIndexPointIntersector; +class QGraphicsSceneIndexPathIntersector; class QGraphicsSceneIndexPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QGraphicsSceneIndex) public: QGraphicsSceneIndexPrivate(QGraphicsScene *scene); + ~QGraphicsSceneIndexPrivate(); - void recursive_items_helper(QGraphicsItem *item, QRectF rect, QList *items, + void recursive_items_helper(QGraphicsItem *item, QGraphicsSceneIndexIntersector *intersector, QList *items, const QTransform &parentTransform, const QTransform &viewTransform, Qt::ItemSelectionMode mode, Qt::SortOrder order, qreal parentOpacity = 1.0) const; - - void childItems_helper(QList *items, - const QGraphicsItem *parent, - const QPointF &pos) const; - void childItems_helper(QList *items, - const QGraphicsItem *parent, - const QPolygonF &polygon, - Qt::ItemSelectionMode mode) const; - void childItems_helper(QList *items, - const QGraphicsItem *parent, - const QPainterPath &path, - Qt::ItemSelectionMode mode) const; - QGraphicsScene *scene; + QGraphicsSceneIndexPointIntersector *pointIntersector; + QGraphicsSceneIndexRectIntersector *rectIntersector; + QGraphicsSceneIndexPathIntersector *pathIntersector; +}; + +class QGraphicsSceneIndexIntersector +{ +public: + QGraphicsSceneIndexIntersector(QGraphicsScene *scene) : scene(scene) { } + virtual ~QGraphicsSceneIndexIntersector() { } + virtual bool intersect(const QRectF &rect) const = 0; + Qt::ItemSelectionMode mode; + QGraphicsItem *item; + QGraphicsScene *scene; + QRectF rect; + QTransform transform; }; QT_END_NAMESPACE -- cgit v0.12 From 3dce31e5eb0fac43d445fb9664f1b68f4cd4c11f Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Tue, 16 Jun 2009 10:26:34 +0200 Subject: Warnings -- --- src/gui/graphicsview/qgraphicssceneindex.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index 8d18806..3c4efe7 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -395,10 +395,11 @@ void QGraphicsSceneIndex::deleteItem(QGraphicsItem *item) \sa GraphicsItemChange */ -void QGraphicsSceneIndex::itemChanged(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange, const QVariant &value) +void QGraphicsSceneIndex::itemChanged(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value) { - //Q_UNUSED(item); - //Q_UNUSED(value); + Q_UNUSED(item); + Q_UNUSED(change); + Q_UNUSED(value); } /*! @@ -408,7 +409,7 @@ void QGraphicsSceneIndex::itemChanged(const QGraphicsItem *item, QGraphicsItem:: */ void QGraphicsSceneIndex::prepareBoundingRectChange(const QGraphicsItem *item) { - //Q_UNUSED(item); + Q_UNUSED(item); } /*! @@ -418,6 +419,7 @@ void QGraphicsSceneIndex::prepareBoundingRectChange(const QGraphicsItem *item) */ void QGraphicsSceneIndex::sceneRectChanged(const QRectF &rect) { + Q_UNUSED(rect); } QT_END_NAMESPACE -- cgit v0.12 From 2ceb72068fbb9157a058a1788863b68a12d25646 Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Tue, 16 Jun 2009 11:41:35 +0200 Subject: Fix all documentation warnings. --- src/gui/graphicsview/qgraphicsitem.h | 2 - src/gui/graphicsview/qgraphicsscene.cpp | 50 +++++++++---- src/gui/graphicsview/qgraphicssceneindex.cpp | 106 ++++++++++++++++++++++----- 3 files changed, 125 insertions(+), 33 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index 6194249..56a4a3b 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -418,8 +418,6 @@ protected: virtual void setExtension(Extension extension, const QVariant &variant); virtual QVariant extension(const QVariant &variant) const; - bool operator<(const QGraphicsItem *other) const; - protected: QGraphicsItem(QGraphicsItemPrivate &dd, QGraphicsItem *parent, QGraphicsScene *scene); diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 6e08a76..0729a9d 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -201,6 +201,8 @@ however, is done in constant time. This approach is ideal for dynamic scenes, where many items are added, moved or removed continuously. + \omitvalue CustomIndex + \sa setItemIndexMethod(), bspTreeDepth */ @@ -312,6 +314,9 @@ void QGraphicsScenePrivate::init() q->update(); } +/*! + \internal +*/ QGraphicsScenePrivate *QGraphicsScenePrivate::get(QGraphicsScene *q) { return q->d_func(); @@ -454,11 +459,11 @@ void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item) markDirty(item, QRectF(), false, false, false, false, /*removingItemFromScene=*/true); if (item->d_ptr->inDestructor) { - // Can potentially call item->boundingRect() (virtual function), that's why - // we only can call this function if the item is not in its destructor. + // The item is actually in its destructor, we call the special method in the index. index->deleteItem(item); } else { - // Remove it from the index properly + // Can potentially call item->boundingRect() (virtual function), that's why + // we only can call this function if the item is not in its destructor. index->removeItem(item); } @@ -1569,6 +1574,13 @@ void QGraphicsScene::setItemIndexMethod(ItemIndexMethod method) d->indexMethod = method; } +/*! + \brief the item indexing method. + This method allow to apply an indexing algorithm \a index to the scene, to speed up + item discovery functions like items() and itemAt(). + + \sa sceneIndex(), QGraphicsSceneIndex +*/ void QGraphicsScene::setSceneIndex(QGraphicsSceneIndex *index) { Q_D(QGraphicsScene); @@ -1583,6 +1595,11 @@ void QGraphicsScene::setSceneIndex(QGraphicsSceneIndex *index) } } +/*! + This method return the current indexing algorithm of the scene. + + \sa setSceneIndex(), QGraphicsSceneIndex +*/ QGraphicsSceneIndex* QGraphicsScene::sceneIndex() const { Q_D(const QGraphicsScene); @@ -1784,10 +1801,13 @@ QList QGraphicsScene::items(const QPainterPath &path, Qt::ItemS } /*! - Returns all visible items at position \a pos in the scene. + Returns all visible items that, depending on \a mode, are at the specified \a pos + and return a list sorted using \a order. The default value for \a mode is Qt::IntersectsItemShape; all items whose - exact shape intersects with or is contained by \a path are returned. + exact shape intersects with \a pos are returned. + + \a deviceTransform is the transformation apply to the view. \sa itemAt() */ @@ -1798,15 +1818,15 @@ QList QGraphicsScene::items(const QPointF &pos, Qt::ItemSelecti } /*! - \fn QList QGraphicsScene::items(const QRectF &rectangle, Qt::SortOrder order, const QTransform &deviceTransform) const - \overload Returns all visible items that, depending on \a mode, are either inside or - intersect with the specified \a rectangle. + intersect with the specified \a rect and return a list sorted using \a order. The default value for \a mode is Qt::IntersectsItemShape; all items whose - exact shape intersects with or is contained by \a rectangle are returned. + exact shape intersects with or is contained by \a rect are returned. + + \a deviceTransform is the transformation apply to the view. \sa itemAt() */ @@ -1820,11 +1840,13 @@ QList QGraphicsScene::items(const QRectF &rect, Qt::ItemSelecti \overload Returns all visible items that, depending on \a mode, are either inside or - intersect with the polygon \a polygon. + intersect with the specified \a polygon and return a list sorted using \a order. The default value for \a mode is Qt::IntersectsItemShape; all items whose exact shape intersects with or is contained by \a polygon are returned. + \a deviceTransform is the transformation apply to the view. + \sa itemAt() */ QList QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const @@ -1834,14 +1856,16 @@ QList QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemS } /*! - \overload + \overload - Returns all visible items that, depending on \a path, are either inside or - intersect with the path \a path. + Returns all visible items that, depending on \a mode, are either inside or + intersect with the specified \a path and return a list sorted using \a order. The default value for \a mode is Qt::IntersectsItemShape; all items whose exact shape intersects with or is contained by \a path are returned. + \a deviceTransform is the transformation apply to the view. + \sa itemAt() */ QList QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index 3c4efe7..b713452 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -38,6 +38,22 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ +/*! + \class QGraphicsSceneIndex + \brief The QGraphicsSceneIndex class provides a base class to implement + a custom indexing algorithm for discovering items in QGraphicsScene. + \since 4.6 + \ingroup multimedia + \ingroup graphicsview-api + \mainclass + + The QGraphicsSceneIndex class provides a base class to implement + a custom indexing algorithm for discovering items in QGraphicsScene. You + need to subclass it and reimplement addItem, removeItem, estimateItems + and items in order to have an functional indexing. + + \sa QGraphicsScene, QGraphicsView +*/ #include "qgraphicssceneindex.h" #include "qgraphicssceneindex_p.h" @@ -229,7 +245,7 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QGr } /*! - Constructs an abstract scene index. + Constructs an abstract scene index for a given \a scene. */ QGraphicsSceneIndex::QGraphicsSceneIndex(QGraphicsScene *scene) : QObject(*new QGraphicsSceneIndexPrivate(scene), scene) @@ -271,12 +287,17 @@ QRectF QGraphicsSceneIndex::indexedRect() const } /*! - \fn QList items() const = 0 + \fn QList QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const - This pure virtual function return the list of items that are actually in the index. + Returns all visible items that, depending on \a mode, are at the specified \a pos + and return a list sorted using \a order. -*/ + The default value for \a mode is Qt::IntersectsItemShape; all items whose + exact shape intersects with \a pos are returned. + + \a deviceTransform is the transformation apply to the view. +*/ QList QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const { Q_D(const QGraphicsSceneIndex); @@ -288,6 +309,20 @@ QList QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSe return itemList; } +/*! + \fn QList QGraphicsSceneIndex::items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const + + \overload + + Returns all visible items that, depending on \a mode, are either inside or + intersect with the specified \a rect and return a list sorted using \a order. + + The default value for \a mode is Qt::IntersectsItemShape; all items whose + exact shape intersects with or is contained by \a rect are returned. + + \a deviceTransform is the transformation apply to the view. + +*/ QList QGraphicsSceneIndex::items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const { Q_D(const QGraphicsSceneIndex); @@ -298,6 +333,20 @@ QList QGraphicsSceneIndex::items(const QRectF &rect, Qt::ItemSe return itemList; } +/*! + \fn QList QGraphicsSceneIndex::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const + + \overload + + Returns all visible items that, depending on \a mode, are either inside or + intersect with the specified \a polygon and return a list sorted using \a order. + + The default value for \a mode is Qt::IntersectsItemShape; all items whose + exact shape intersects with or is contained by \a polygon are returned. + + \a deviceTransform is the transformation apply to the view. + +*/ QList QGraphicsSceneIndex::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const { Q_D(const QGraphicsSceneIndex); @@ -313,6 +362,20 @@ QList QGraphicsSceneIndex::items(const QPolygonF &polygon, Qt:: return itemList; } +/*! + \fn QList QGraphicsSceneIndex::items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const + + \overload + + Returns all visible items that, depending on \a mode, are either inside or + intersect with the specified \a path and return a list sorted using \a order. + + The default value for \a mode is Qt::IntersectsItemShape; all items whose + exact shape intersects with or is contained by \a path are returned. + + \a deviceTransform is the transformation apply to the view. + +*/ QList QGraphicsSceneIndex::items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const { Q_D(const QGraphicsSceneIndex); @@ -327,8 +390,9 @@ QList QGraphicsSceneIndex::items(const QPainterPath &path, Qt:: } /*! - This pure virtual function return an estimation of items at position \a pos. - + This virtual function return an estimation of items at position \a point. + This method return a list sorted using \a order. + \a deviceTransform is the transformation apply to the view. */ QList QGraphicsSceneIndex::estimateItems(const QPointF &point, Qt::SortOrder order, const QTransform &deviceTransform) const { @@ -336,12 +400,18 @@ QList QGraphicsSceneIndex::estimateItems(const QPointF &point, } /*! - \fn virtual QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const = 0 + \fn virtual QList QGraphicsSceneIndex::estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const = 0 This pure virtual function return an estimation of items in the \a rect. + This method return a list sorted using \a order. + \a deviceTransform is the transformation apply to the view. */ +/*! + \fn virtual QList QGraphicsSceneIndex::items(Qt::SortOrder order = Qt::AscendingOrder) const = 0; + This pure virtual function all items in the index and sort them using \a order. +*/ /*! This virtual function removes all items in the scene index. @@ -353,23 +423,23 @@ void QGraphicsSceneIndex::clear() } /*! - \fn virtual void addItem(QGraphicsItem *item) = 0 + \fn virtual void QGraphicsSceneIndex::addItem(QGraphicsItem *item) = 0 - This pure virtual function inserts an item to the scene index. + This pure virtual function inserts an \a item to the scene index. \sa removeItem(), deleteItem() */ /*! - \fn virtual void removeItem(QGraphicsItem *item) = 0 + \fn virtual void QGraphicsSceneIndex::removeItem(QGraphicsItem *item) = 0 - This pure virtual function removes an item to the scene index. + This pure virtual function removes an \a item to the scene index. \sa addItem(), deleteItem() */ /*! - This method is called when an item has been deleted. + This method is called when an \a item has been deleted. The default implementation call removeItem. Be carefull, if your implementation of removeItem use pure virtual method of QGraphicsItem like boundingRect(), then you should reimplement @@ -384,7 +454,7 @@ void QGraphicsSceneIndex::deleteItem(QGraphicsItem *item) /*! This virtual function is called by QGraphicsItem to notify the index - that some part of the item's state changes. By reimplementing this + that some part of the \a item 's state changes. By reimplementing this function, your can react to a change, and in some cases, (depending on \a change,) adjustments in the index can be made. @@ -393,7 +463,7 @@ void QGraphicsSceneIndex::deleteItem(QGraphicsItem *item) The default implementation does nothing. - \sa GraphicsItemChange + \sa QGraphicsItem::GraphicsItemChange */ void QGraphicsSceneIndex::itemChanged(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value) { @@ -403,9 +473,9 @@ void QGraphicsSceneIndex::itemChanged(const QGraphicsItem *item, QGraphicsItem:: } /*! - Notify the index for a geometry change of an item. + Notify the index for a geometry change of an \a item. - \sa QGraphicsItem::prepareGeometryChange + \sa QGraphicsItem::prepareGeometryChange() */ void QGraphicsSceneIndex::prepareBoundingRectChange(const QGraphicsItem *item) { @@ -414,8 +484,8 @@ void QGraphicsSceneIndex::prepareBoundingRectChange(const QGraphicsItem *item) /*! This virtual function is called when the scene changes its bounding - rectangle. - \sa QGraphicsScene::sceneRect + rectangle. \a rect is the new value of the scene rectangle. + \sa QGraphicsScene::sceneRect() */ void QGraphicsSceneIndex::sceneRectChanged(const QRectF &rect) { -- cgit v0.12 From 0fa15d71015adfd8895ef41a082fb9479bf4bb3d Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Tue, 16 Jun 2009 13:45:36 +0200 Subject: Remove old legacy and fix documentation. --- src/gui/graphicsview/graphicsview.pri | 1 + src/gui/graphicsview/qgraphicsscene.cpp | 12 +- src/gui/graphicsview/qgraphicsscene_p.h | 4 +- .../graphicsview/qgraphicsscenebsptreeindex_p.cpp | 145 ++++++++++++++++++++- .../graphicsview/qgraphicsscenebsptreeindex_p.h | 5 +- src/gui/graphicsview/qgraphicssceneindex.cpp | 27 ++++ src/gui/graphicsview/qgraphicsscenelinearindex_p.h | 37 +++--- 7 files changed, 198 insertions(+), 33 deletions(-) diff --git a/src/gui/graphicsview/graphicsview.pri b/src/gui/graphicsview/graphicsview.pri index 9dc4112..a4d142a 100644 --- a/src/gui/graphicsview/graphicsview.pri +++ b/src/gui/graphicsview/graphicsview.pri @@ -18,6 +18,7 @@ SOURCES += graphicsview/qgraphicsitem.cpp \ graphicsview/qgraphicsscene.cpp \ graphicsview/qgraphicsscene_bsp.cpp \ graphicsview/qgraphicsscenebsptreeindex_p.cpp \ + graphicsview/qgraphicsscenelinearindex.cpp \ graphicsview/qgraphicssceneindex.cpp \ graphicsview/qgraphicssceneevent.cpp \ graphicsview/qgraphicsview.cpp diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 0729a9d..328ab4c 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -271,9 +271,8 @@ static void _q_hoverFromMouseEvent(QGraphicsSceneHoverEvent *hover, const QGraph QGraphicsScenePrivate::QGraphicsScenePrivate() : changedSignalMask(0), indexMethod(QGraphicsScene::BspTreeIndex), - bspTreeDepth(0), - lastItemCount(0), index(0), + lastItemCount(0), hasSceneRect(false), updateAll(false), calledEmitUpdated(false), @@ -1642,14 +1641,11 @@ int QGraphicsScene::bspTreeDepth() const { Q_D(const QGraphicsScene); QGraphicsSceneBspTreeIndex *bspTree = qobject_cast(d->index); - return bspTree ? bspTree->bspDepth() : 0; + return bspTree ? bspTree->bspTreeDepth() : 0; } void QGraphicsScene::setBspTreeDepth(int depth) { Q_D(QGraphicsScene); - if (d->bspTreeDepth == depth) - return; - if (depth < 0) { qWarning("QGraphicsScene::setBspTreeDepth: invalid depth %d ignored; must be >= 0", depth); return; @@ -1660,8 +1656,10 @@ void QGraphicsScene::setBspTreeDepth(int depth) qWarning("QGraphicsScene::setBspTreeDepth: can not apply if indexing method is not BSP"); return; } + if (bspTree->bspTreeDepth() == depth) + return; - bspTree->setBspDepth(depth); + bspTree->setBspTreeDepth(depth); } /*! diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index c63e121..db401ef 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -90,12 +90,10 @@ public: quint32 changedSignalMask; QGraphicsScene::ItemIndexMethod indexMethod; - int bspTreeDepth; + QGraphicsSceneIndex *index; int lastItemCount; - QGraphicsSceneIndex *index; - QRectF sceneRect; bool hasSceneRect; QRectF growingItemsBoundingRect; diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp index acadcbd..b19248a 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp @@ -39,6 +39,40 @@ ** ****************************************************************************/ +/*! + \class QGraphicsSceneBspTreeIndex + \brief The QGraphicsSceneBspTreeIndex class provides an implementation of + a BSP indexing algorithm for discovering items in QGraphicsScene. + \since 4.6 + \ingroup multimedia + \ingroup graphicsview-api + \mainclass + + QGraphicsSceneBspTreeIndex index use a BSP(Binary Space Partitioning) + implementation to discover items quickly. This implementation is + very efficient for static scene. It has a depth that you can set. + The depth directly affects performance and memory usage; the latter + growing exponentially with the depth of the tree. With an optimal tree + depth, the index can instantly determine the locality of items, even + for scenes with thousands or millions of items. This also greatly improves + rendering performance. + + By default, the value is 0, in which case Qt will guess a reasonable + default depth based on the size, location and number of items in the + scene. If these parameters change frequently, however, you may experience + slowdowns as the index retunes the depth internally. You can avoid + potential slowdowns by fixating the tree depth through setting this + property. + + The depth of the tree and the size of the scene rectangle decide the + granularity of the scene's partitioning. The size of each scene segment is + determined by the following algorithm: + + The BSP tree has an optimal size when each segment contains between 0 and + 10 items. + + \sa QGraphicsScene, QGraphicsView, QGraphicsSceneIndex +*/ #include "qgraphicsscenebsptreeindex_p.h" @@ -61,7 +95,7 @@ static inline int intmaxlog(int n) } /*! - Constructs a private scene index. + Constructs a private scene bsp index. */ QGraphicsSceneBspTreeIndexPrivate::QGraphicsSceneBspTreeIndexPrivate(QGraphicsScene *scene) : QGraphicsSceneIndexPrivate(scene), @@ -78,6 +112,11 @@ QGraphicsSceneBspTreeIndexPrivate::QGraphicsSceneBspTreeIndexPrivate(QGraphicsSc /*! + This method will update the BSP index by removing the items from the temporary + unindexed list and add them in the indexedItems list. This will also + update the growingItemsBoundingRect if needed. This will update the BSP + implementation as well. + \internal */ void QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex() @@ -223,6 +262,9 @@ void QGraphicsSceneBspTreeIndexPrivate::resetIndex() startIndexTimer(); } +/*! + \internal +*/ void QGraphicsSceneBspTreeIndexPrivate::climbTree(QGraphicsItem *item, int *stackingOrder) { if (!item->d_ptr->children.isEmpty()) { @@ -244,6 +286,9 @@ void QGraphicsSceneBspTreeIndexPrivate::climbTree(QGraphicsItem *item, int *stac } } +/*! + \internal +*/ void QGraphicsSceneBspTreeIndexPrivate::_q_updateSortCache() { Q_Q(QGraphicsSceneBspTreeIndex); @@ -268,6 +313,9 @@ void QGraphicsSceneBspTreeIndexPrivate::_q_updateSortCache() climbTree(topLevels.at(i), &stackingOrder); } +/*! + \internal +*/ void QGraphicsSceneBspTreeIndexPrivate::invalidateSortCache() { Q_Q(QGraphicsSceneBspTreeIndex); @@ -342,6 +390,11 @@ bool QGraphicsSceneBspTreeIndexPrivate::closestItemLast_withoutCache(const QGrap return closestItemFirst_withoutCache(item2, item1); } +/*! + Sort a list of \a itemList in a specific \a order and use the cache if requested. + + \internal +*/ void QGraphicsSceneBspTreeIndexPrivate::sortItems(QList *itemList, Qt::SortOrder order, bool sortCacheEnabled) { @@ -360,12 +413,19 @@ void QGraphicsSceneBspTreeIndexPrivate::sortItems(QList *itemLi } } +/*! + Constructs a BSP scene index for the given \a scene. +*/ QGraphicsSceneBspTreeIndex::QGraphicsSceneBspTreeIndex(QGraphicsScene *scene) : QGraphicsSceneIndex(*new QGraphicsSceneBspTreeIndexPrivate(scene), scene) { } +/*! + \reimp + Return the rect indexed by the BSP index. +*/ QRectF QGraphicsSceneBspTreeIndex::indexedRect() const { Q_D(const QGraphicsSceneBspTreeIndex); @@ -373,6 +433,10 @@ QRectF QGraphicsSceneBspTreeIndex::indexedRect() const return scene()->d_func()->hasSceneRect ? scene()->d_func()->sceneRect : scene()->d_func()->growingItemsBoundingRect; } +/*! + \reimp + Clear the all the BSP index. +*/ void QGraphicsSceneBspTreeIndex::clear() { Q_D(QGraphicsSceneBspTreeIndex); @@ -383,6 +447,9 @@ void QGraphicsSceneBspTreeIndex::clear() d->unindexedItems.clear(); } +/*! + Add the \a item into the BSP index. +*/ void QGraphicsSceneBspTreeIndex::addItem(QGraphicsItem *item) { Q_D(QGraphicsSceneBspTreeIndex); @@ -405,6 +472,7 @@ void QGraphicsSceneBspTreeIndex::addItem(QGraphicsItem *item) } /*! + This really add the item in the BSP. \internal */ void QGraphicsSceneBspTreeIndexPrivate::addToIndex(QGraphicsItem *item) @@ -421,6 +489,9 @@ void QGraphicsSceneBspTreeIndexPrivate::addToIndex(QGraphicsItem *item) } } +/*! + Remove the \a item from the BSP index. +*/ void QGraphicsSceneBspTreeIndex::removeItem(QGraphicsItem *item) { Q_D(QGraphicsSceneBspTreeIndex); @@ -443,6 +514,10 @@ void QGraphicsSceneBspTreeIndex::removeItem(QGraphicsItem *item) } } +/*! + \reimp + Delete the \a item from the BSP index (without accessing its boundingRect). +*/ void QGraphicsSceneBspTreeIndex::deleteItem(QGraphicsItem *item) { Q_D(QGraphicsSceneBspTreeIndex); @@ -469,6 +544,7 @@ void QGraphicsSceneBspTreeIndex::deleteItem(QGraphicsItem *item) } /*! + Really remove the item from the BSP \internal */ void QGraphicsSceneBspTreeIndexPrivate::removeFromIndex(QGraphicsItem *item) @@ -492,6 +568,10 @@ void QGraphicsSceneBspTreeIndexPrivate::removeFromIndex(QGraphicsItem *item) startIndexTimer(); } +/*! + \reimp + Update the BSP when the \a item 's bounding rect has changed. +*/ void QGraphicsSceneBspTreeIndex::prepareBoundingRectChange(const QGraphicsItem *item) { Q_D(QGraphicsSceneBspTreeIndex); @@ -501,6 +581,13 @@ void QGraphicsSceneBspTreeIndex::prepareBoundingRectChange(const QGraphicsItem * d->removeFromIndex(const_cast(item)); } +/*! + Returns an estimation visible items that are either inside or + intersect with the specified \a rect and return a list sorted using \a order. + + \a deviceTransform is the transformation apply to the view. + +*/ QList QGraphicsSceneBspTreeIndex::estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const { Q_D(const QGraphicsSceneBspTreeIndex); @@ -530,6 +617,12 @@ QList QGraphicsSceneBspTreeIndex::estimateItems(const QRectF &r return rectItems; } + +/*! + \fn QList QGraphicsSceneBspTreeIndex::items(Qt::SortOrder order = Qt::AscendingOrder) const; + + Return all items in the BSP index and sort them using \a order. +*/ QList QGraphicsSceneBspTreeIndex::items(Qt::SortOrder order) const { Q_D(const QGraphicsSceneBspTreeIndex); @@ -558,19 +651,52 @@ QList QGraphicsSceneBspTreeIndex::items(Qt::SortOrder order) co return itemList; } -int QGraphicsSceneBspTreeIndex::bspDepth() +/*! + \property QGraphicsSceneBspTreeIndex::bspTreeDepth + \brief the depth of the BSP index tree + \since 4.6 + + This value determines the depth of BSP tree. The depth + directly affects performance and memory usage; the latter + growing exponentially with the depth of the tree. With an optimal tree + depth, the index can instantly determine the locality of items, even + for scenes with thousands or millions of items. This also greatly improves + rendering performance. + + By default, the value is 0, in which case Qt will guess a reasonable + default depth based on the size, location and number of items in the + scene. If these parameters change frequently, however, you may experience + slowdowns as the index retunes the depth internally. You can avoid + potential slowdowns by fixating the tree depth through setting this + property. + + The depth of the tree and the size of the scene rectangle decide the + granularity of the scene's partitioning. The size of each scene segment is + determined by the following algorithm: + + The BSP tree has an optimal size when each segment contains between 0 and + 10 items. + +*/ +int QGraphicsSceneBspTreeIndex::bspTreeDepth() { Q_D(const QGraphicsSceneBspTreeIndex); return d->bspTreeDepth; } -void QGraphicsSceneBspTreeIndex::setBspDepth(int depth) +void QGraphicsSceneBspTreeIndex::setBspTreeDepth(int depth) { Q_D(QGraphicsSceneBspTreeIndex); d->bspTreeDepth = depth; d->resetIndex(); } +/*! + \reimp + + This method react to the \a rect change of the scene and + reset the BSP tree index. +*/ void QGraphicsSceneBspTreeIndex::sceneRectChanged(const QRectF &rect) { Q_D(QGraphicsSceneBspTreeIndex); @@ -578,6 +704,13 @@ void QGraphicsSceneBspTreeIndex::sceneRectChanged(const QRectF &rect) d->resetIndex(); } +/*! + \reimp + + This method react to the \a change of the \a item and use the \a value to + update the BSP tree if necessary. + +*/ void QGraphicsSceneBspTreeIndex::itemChanged(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value) { Q_D(QGraphicsSceneBspTreeIndex); @@ -592,7 +725,13 @@ void QGraphicsSceneBspTreeIndex::itemChanged(const QGraphicsItem *item, QGraphic } return QGraphicsSceneIndex::itemChanged(item, change, value); } +/*! + \reimp + Used to catch the timer event. + + \internal +*/ bool QGraphicsSceneBspTreeIndex::event(QEvent *event) { Q_D(QGraphicsSceneBspTreeIndex); diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h index b1ea977..40b8f0b 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h @@ -60,6 +60,7 @@ class QGraphicsSceneBspTreeIndexPrivate; class Q_AUTOTEST_EXPORT QGraphicsSceneBspTreeIndex : public QGraphicsSceneIndex { Q_OBJECT + Q_PROPERTY(int bspTreeDepth READ bspTreeDepth WRITE setBspTreeDepth) public: QGraphicsSceneBspTreeIndex(QGraphicsScene *scene = 0); QRectF indexedRect() const; @@ -68,8 +69,8 @@ public: QList items(Qt::SortOrder order = Qt::AscendingOrder) const; - int bspDepth(); - void setBspDepth(int depth); + int bspTreeDepth(); + void setBspTreeDepth(int depth); protected: bool event(QEvent *event); diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index b713452..05ec28b 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -147,6 +147,9 @@ QGraphicsSceneIndexPrivate::~QGraphicsSceneIndexPrivate() delete pathIntersector; } +/*! + \internal +*/ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QGraphicsSceneIndexIntersector *intersector, QList *items, const QTransform &parentTransform, @@ -297,6 +300,12 @@ QRectF QGraphicsSceneIndex::indexedRect() const \a deviceTransform is the transformation apply to the view. + This method use the estimation of the index (estimateItems) and refine + the list to get an exact result. If you want to implement your own + refinement algorithm you can reimplement this method. + + \sa estimateItems() + */ QList QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const { @@ -322,6 +331,12 @@ QList QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSe \a deviceTransform is the transformation apply to the view. + This method use the estimation of the index (estimateItems) and refine + the list to get an exact result. If you want to implement your own + refinement algorithm you can reimplement this method. + + \sa estimateItems() + */ QList QGraphicsSceneIndex::items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const { @@ -346,6 +361,12 @@ QList QGraphicsSceneIndex::items(const QRectF &rect, Qt::ItemSe \a deviceTransform is the transformation apply to the view. + This method use the estimation of the index (estimateItems) and refine + the list to get an exact result. If you want to implement your own + refinement algorithm you can reimplement this method. + + \sa estimateItems() + */ QList QGraphicsSceneIndex::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const { @@ -375,6 +396,12 @@ QList QGraphicsSceneIndex::items(const QPolygonF &polygon, Qt:: \a deviceTransform is the transformation apply to the view. + This method use the estimation of the index (estimateItems) and refine + the list to get an exact result. If you want to implement your own + refinement algorithm you can reimplement this method. + + \sa estimateItems() + */ QList QGraphicsSceneIndex::items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const { diff --git a/src/gui/graphicsview/qgraphicsscenelinearindex_p.h b/src/gui/graphicsview/qgraphicsscenelinearindex_p.h index 3057b4a..d21475c 100644 --- a/src/gui/graphicsview/qgraphicsscenelinearindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenelinearindex_p.h @@ -68,23 +68,32 @@ class Q_AUTOTEST_EXPORT QGraphicsSceneLinearIndex : public QGraphicsSceneIndex { Q_OBJECT -private: - QRectF m_sceneRect; - QList m_items; - public: QGraphicsSceneLinearIndex(QGraphicsScene *scene = 0): QGraphicsSceneIndex(scene) { } - virtual void setRect(const QRectF &rect) { - m_sceneRect = rect; + QList items(Qt::SortOrder order = Qt::AscendingOrder) const { + Q_UNUSED(order); + return m_items; + } + + virtual QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const { + Q_UNUSED(rect); + Q_UNUSED(order); + Q_UNUSED(deviceTransform); + return m_items; } - virtual QRectF rect() const { + virtual QRectF indexedRect() const { return m_sceneRect; } +protected : + void sceneRectChanged(const QRectF &rect) { + m_sceneRect = rect; + } + virtual void clear() { m_items.clear(); } @@ -97,17 +106,9 @@ public: m_items.removeAll(item); } - virtual QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const { - QList result; - foreach (QGraphicsItem *item, m_items) - if (item->sceneBoundingRect().intersects(rect)) - result << item; - return result; - } - - QList items(Qt::SortOrder order = Qt::AscendingOrder) const { - return m_items; - } +private: + QRectF m_sceneRect; + QList m_items; }; QT_END_NAMESPACE -- cgit v0.12 From 8dee7b0c5be293f4b8ebafcae6baa052ca92f1d0 Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Tue, 16 Jun 2009 13:46:43 +0200 Subject: Add missing file. --- src/gui/graphicsview/qgraphicsscenelinearindex.cpp | 70 ++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 src/gui/graphicsview/qgraphicsscenelinearindex.cpp diff --git a/src/gui/graphicsview/qgraphicsscenelinearindex.cpp b/src/gui/graphicsview/qgraphicsscenelinearindex.cpp new file mode 100644 index 0000000..1c898bc --- /dev/null +++ b/src/gui/graphicsview/qgraphicsscenelinearindex.cpp @@ -0,0 +1,70 @@ +#include "qgraphicsscenelinearindex_p.h" + +/*! + \class QGraphicsSceneLinearIndex + \brief The QGraphicsSceneLinearIndex class provides an implementation of + a linear indexing algorithm for discovering items in QGraphicsScene. + \since 4.6 + \ingroup multimedia + \ingroup graphicsview-api + \mainclass + + QGraphicsSceneLinearIndex index is default linear implementation to discover items. + It basically store all items in a list and return them to the scene. + + \sa QGraphicsScene, QGraphicsView, QGraphicsSceneIndex, QGraphicsSceneBspTreeIndex +*/ + +/*! + \fn QGraphicsSceneLinearIndex::QGraphicsSceneLinearIndex(QGraphicsScene *scene = 0): + + Construct a linear index for the given \a scene. +*/ + +/*! + \fn QList QGraphicsSceneLinearIndex::items(Qt::SortOrder order = Qt::AscendingOrder) const; + + Return all items in the index and sort them using \a order. +*/ + + +/*! + \fn virtual QList QGraphicsSceneLinearIndex::estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const; + + Returns an estimation visible items that are either inside or + intersect with the specified \a rect and return a list sorted using \a order. + + \a deviceTransform is the transformation apply to the view. + +*/ + +/*! + \fn QRectF QGraphicsSceneLinearIndex::indexedRect() const; + \reimp + Return the rect indexed by the the index. +*/ + +/*! + \fn void QGraphicsSceneLinearIndex::sceneRectChanged(const QRectF &rect); + \reimp + This method react to the \a rect change of the scene. +*/ + +/*! + \fn void QGraphicsSceneLinearIndex::clear(); + \reimp + Clear the all the BSP index. +*/ + +/*! + \fn virtual void QGraphicsSceneLinearIndex::addItem(QGraphicsItem *item); + + Add the \a item into the index. +*/ + +/*! + \fn virtual void QGraphicsSceneLinearIndex::removeItem(QGraphicsItem *item); + + Add the \a item from the index. +*/ + -- cgit v0.12 From d72727cb7530da54b59c51effa97263512e9238c Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Wed, 17 Jun 2009 11:25:36 +0200 Subject: Fix broken auto-test for the index. Since now items() doesn't use the index then the growingboundingrect is not updated if you call right after a delete. It's because the timer is not yet fired (even the processEvent) so you call add, move, remove which will trigger only one update index so the growingboundingrect will never change. --- tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp index 4d786c7..17d290b 100644 --- a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp +++ b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp @@ -2726,8 +2726,8 @@ void tst_QGraphicsScene::update() qRegisterMetaType >("QList"); QSignalSpy spy(&scene, SIGNAL(changed(QList))); - // When deleted, the item will lazy-remove itself - delete rect; + // We update the scene. + scene.update(); // This function forces a purge, which will post an update signal scene.itemAt(0, 0); -- cgit v0.12 From 8a0e002ccc762ef3edbc3c9ad91b4d6017cb91bb Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Wed, 17 Jun 2009 14:15:14 +0200 Subject: Make eveything internal for now but ready to see the light. --- src/gui/graphicsview/graphicsview.pri | 6 +- src/gui/graphicsview/qgraphicsitem.cpp | 2 +- src/gui/graphicsview/qgraphicsscene.cpp | 7 +- src/gui/graphicsview/qgraphicsscene_p.h | 1 - .../graphicsview/qgraphicsscenebsptreeindex.cpp | 761 +++++++++++++++++++++ src/gui/graphicsview/qgraphicsscenebsptreeindex.h | 119 ++++ .../graphicsview/qgraphicsscenebsptreeindex_p.cpp | 760 -------------------- .../graphicsview/qgraphicsscenebsptreeindex_p.h | 137 ++-- .../graphicsview/qgraphicsscenebsptreeindex_p_p.h | 150 ---- src/gui/graphicsview/qgraphicssceneindex.cpp | 2 +- src/gui/graphicsview/qgraphicssceneindex.h | 13 +- src/gui/graphicsview/qgraphicsscenelinearindex.cpp | 3 +- src/gui/graphicsview/qgraphicsscenelinearindex.h | 124 ++++ src/gui/graphicsview/qgraphicsscenelinearindex_p.h | 118 ---- 14 files changed, 1122 insertions(+), 1081 deletions(-) create mode 100644 src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp create mode 100644 src/gui/graphicsview/qgraphicsscenebsptreeindex.h delete mode 100644 src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp delete mode 100644 src/gui/graphicsview/qgraphicsscenebsptreeindex_p_p.h create mode 100644 src/gui/graphicsview/qgraphicsscenelinearindex.h delete mode 100644 src/gui/graphicsview/qgraphicsscenelinearindex_p.h diff --git a/src/gui/graphicsview/graphicsview.pri b/src/gui/graphicsview/graphicsview.pri index a4d142a..5ac1c54 100644 --- a/src/gui/graphicsview/graphicsview.pri +++ b/src/gui/graphicsview/graphicsview.pri @@ -5,11 +5,11 @@ HEADERS += graphicsview/qgraphicsitem.h \ graphicsview/qgraphicsscene.h \ graphicsview/qgraphicsscene_p.h \ graphicsview/qgraphicsscene_bsp_p.h \ - graphicsview/qgraphicsscenelinearindex_p.h \ + graphicsview/qgraphicsscenelinearindex.h \ graphicsview/qgraphicssceneindex.h \ graphicsview/qgraphicssceneindex_p.h \ + graphicsview/qgraphicsscenebsptreeindex.h \ graphicsview/qgraphicsscenebsptreeindex_p.h \ - graphicsview/qgraphicsscenebsptreeindex_p_p.h \ graphicsview/qgraphicssceneevent.h \ graphicsview/qgraphicsview_p.h \ graphicsview/qgraphicsview.h @@ -17,7 +17,7 @@ SOURCES += graphicsview/qgraphicsitem.cpp \ graphicsview/qgraphicsitemanimation.cpp \ graphicsview/qgraphicsscene.cpp \ graphicsview/qgraphicsscene_bsp.cpp \ - graphicsview/qgraphicsscenebsptreeindex_p.cpp \ + graphicsview/qgraphicsscenebsptreeindex.cpp \ graphicsview/qgraphicsscenelinearindex.cpp \ graphicsview/qgraphicssceneindex.cpp \ graphicsview/qgraphicssceneevent.cpp \ diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 39ad447..593d7be 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -554,7 +554,7 @@ #include "qgraphicsview.h" #include "qgraphicswidget.h" #include "qgraphicsproxywidget.h" -#include "qgraphicsscenebsptreeindex_p_p.h" +#include "qgraphicsscenebsptreeindex_p.h" #include #include #include diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 5a3028c..a33cb3e 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -220,7 +220,8 @@ #include "qgraphicswidget.h" #include "qgraphicswidget_p.h" #include "qgraphicssceneindex.h" -#include "qgraphicsscenebsptreeindex_p_p.h" +#include "qgraphicsscenebsptreeindex.h" +#include "qgraphicsscenelinearindex.h" #include #include @@ -1574,6 +1575,8 @@ void QGraphicsScene::setItemIndexMethod(ItemIndexMethod method) } /*! + \internal + \brief the item indexing method. This method allow to apply an indexing algorithm \a index to the scene, to speed up item discovery functions like items() and itemAt(). @@ -1595,6 +1598,8 @@ void QGraphicsScene::setSceneIndex(QGraphicsSceneIndex *index) } /*! + \internal + This method return the current indexing algorithm of the scene. \sa setSceneIndex(), QGraphicsSceneIndex diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 72ae158..563e016 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -58,7 +58,6 @@ #if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW #include "qgraphicsscenebsptreeindex_p.h" -#include "qgraphicsscenelinearindex_p.h" #include "qgraphicssceneindex.h" #include "qgraphicsview.h" #include "qgraphicsitem_p.h" diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp new file mode 100644 index 0000000..76fd218 --- /dev/null +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -0,0 +1,761 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \class QGraphicsSceneBspTreeIndex + \brief The QGraphicsSceneBspTreeIndex class provides an implementation of + a BSP indexing algorithm for discovering items in QGraphicsScene. + \since 4.6 + \ingroup multimedia + \ingroup graphicsview-api + \mainclass + \internal + + QGraphicsSceneBspTreeIndex index use a BSP(Binary Space Partitioning) + implementation to discover items quickly. This implementation is + very efficient for static scene. It has a depth that you can set. + The depth directly affects performance and memory usage; the latter + growing exponentially with the depth of the tree. With an optimal tree + depth, the index can instantly determine the locality of items, even + for scenes with thousands or millions of items. This also greatly improves + rendering performance. + + By default, the value is 0, in which case Qt will guess a reasonable + default depth based on the size, location and number of items in the + scene. If these parameters change frequently, however, you may experience + slowdowns as the index retunes the depth internally. You can avoid + potential slowdowns by fixating the tree depth through setting this + property. + + The depth of the tree and the size of the scene rectangle decide the + granularity of the scene's partitioning. The size of each scene segment is + determined by the following algorithm: + + The BSP tree has an optimal size when each segment contains between 0 and + 10 items. + + \sa QGraphicsScene, QGraphicsView, QGraphicsSceneIndex +*/ + +#include "qgraphicsscenebsptreeindex.h" + +#ifndef QT_NO_GRAPHICSVIEW + +#include "qgraphicsscenebsptreeindex_p.h" +#include "qgraphicssceneindex_p.h" +#include "qgraphicsitem_p.h" +#include "qgraphicsscene_p.h" + +#include + +#include + +QT_BEGIN_NAMESPACE + +static inline int intmaxlog(int n) +{ + return (n > 0 ? qMax(qCeil(qLn(qreal(n)) / qLn(qreal(2))), 5) : 0); +} + +/*! + Constructs a private scene bsp index. +*/ +QGraphicsSceneBspTreeIndexPrivate::QGraphicsSceneBspTreeIndexPrivate(QGraphicsScene *scene) + : QGraphicsSceneIndexPrivate(scene), + bspTreeDepth(0), + indexTimerId(0), + restartIndexTimer(false), + regenerateIndex(true), + lastItemCount(0), + purgePending(false), + sortCacheEnabled(false), + updatingSortCache(false) +{ +} + + +/*! + This method will update the BSP index by removing the items from the temporary + unindexed list and add them in the indexedItems list. This will also + update the growingItemsBoundingRect if needed. This will update the BSP + implementation as well. + + \internal +*/ +void QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex() +{ + Q_Q(QGraphicsSceneBspTreeIndex); + if (!indexTimerId) + return; + + QGraphicsScenePrivate * scenePrivate = q->scene()->d_func(); + q->killTimer(indexTimerId); + indexTimerId = 0; + + purgeRemovedItems(); + + // Add unindexedItems to indexedItems + QRectF unindexedItemsBoundingRect; + for (int i = 0; i < unindexedItems.size(); ++i) { + if (QGraphicsItem *item = unindexedItems.at(i)) { + unindexedItemsBoundingRect |= item->sceneBoundingRect(); + if (!freeItemIndexes.isEmpty()) { + int freeIndex = freeItemIndexes.takeFirst(); + item->d_func()->index = freeIndex; + indexedItems[freeIndex] = item; + } else { + item->d_func()->index = indexedItems.size(); + indexedItems << item; + } + } + } + + // Update growing scene rect. + QRectF oldGrowingItemsBoundingRect = scenePrivate->growingItemsBoundingRect; + scenePrivate->growingItemsBoundingRect |= unindexedItemsBoundingRect; + + // Determine whether we should regenerate the BSP tree. + if (bspTreeDepth == 0) { + int oldDepth = intmaxlog(lastItemCount); + bspTreeDepth = intmaxlog(indexedItems.size()); + static const int slack = 100; + if (bsp.leafCount() == 0 || (oldDepth != bspTreeDepth && qAbs(lastItemCount - indexedItems.size()) > slack)) { + // ### Crude algorithm. + regenerateIndex = true; + } + } + + // Regenerate the tree. + if (regenerateIndex) { + regenerateIndex = false; + bsp.initialize(q->scene()->sceneRect(), bspTreeDepth); + unindexedItems = indexedItems; + lastItemCount = indexedItems.size(); + q->scene()->update(); + + // Take this opportunity to reset our largest-item counter for + // untransformable items. When the items are inserted into the BSP + // tree, we'll get an accurate calculation. + scenePrivate->largestUntransformableItem = QRectF(); + } + + // Insert all unindexed items into the tree. + for (int i = 0; i < unindexedItems.size(); ++i) { + if (QGraphicsItem *item = unindexedItems.at(i)) { + QRectF rect = item->sceneBoundingRect(); + if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) + continue; + + bsp.insertItem(item, rect); + + // If the item ignores view transformations, update our + // largest-item-counter to ensure that the view can accurately + // discover untransformable items when drawing. + if (item->d_ptr->itemIsUntransformable()) { + QGraphicsItem *topmostUntransformable = item; + while (topmostUntransformable && (topmostUntransformable->d_ptr->ancestorFlags + & QGraphicsItemPrivate::AncestorIgnoresTransformations)) { + topmostUntransformable = topmostUntransformable->parentItem(); + } + // ### Verify that this is the correct largest untransformable rectangle. + scenePrivate->largestUntransformableItem |= item->mapToItem(topmostUntransformable, item->boundingRect()).boundingRect(); + } + } + } + unindexedItems.clear(); + + // Notify scene rect changes. + if (!scenePrivate->hasSceneRect && scenePrivate->growingItemsBoundingRect != oldGrowingItemsBoundingRect) + emit q->scene()->sceneRectChanged(scenePrivate->growingItemsBoundingRect); +} + + +/*! + \internal + + Removes stale pointers from all data structures. +*/ +void QGraphicsSceneBspTreeIndexPrivate::purgeRemovedItems() +{ + if (!purgePending && removedItems.isEmpty()) + return; + + // Remove stale items from the BSP tree. + bsp.removeItems(removedItems); + // Purge this list. + removedItems.clear(); + freeItemIndexes.clear(); + for (int i = 0; i < indexedItems.size(); ++i) { + if (!indexedItems.at(i)) + freeItemIndexes << i; + } + purgePending = false; +} + +/*! + \internal + + Starts or restarts the timer used for reindexing unindexed items. +*/ +void QGraphicsSceneBspTreeIndexPrivate::startIndexTimer(int interval) +{ + Q_Q(QGraphicsSceneBspTreeIndex); + if (indexTimerId) { + restartIndexTimer = true; + } else { + indexTimerId = q->startTimer(interval); + } +} + +/*! + \internal +*/ +void QGraphicsSceneBspTreeIndexPrivate::resetIndex() +{ + purgeRemovedItems(); + for (int i = 0; i < indexedItems.size(); ++i) { + if (QGraphicsItem *item = indexedItems.at(i)) { + item->d_ptr->index = -1; + unindexedItems << item; + } + } + indexedItems.clear(); + freeItemIndexes.clear(); + regenerateIndex = true; + startIndexTimer(); +} + +/*! + \internal +*/ +void QGraphicsSceneBspTreeIndexPrivate::climbTree(QGraphicsItem *item, int *stackingOrder) +{ + if (!item->d_ptr->children.isEmpty()) { + QList childList = item->d_ptr->children; + qSort(childList.begin(), childList.end(), qt_closestLeaf); + for (int i = 0; i < childList.size(); ++i) { + QGraphicsItem *item = childList.at(i); + if (!(item->flags() & QGraphicsItem::ItemStacksBehindParent)) + climbTree(childList.at(i), stackingOrder); + } + item->d_ptr->globalStackingOrder = (*stackingOrder)++; + for (int i = 0; i < childList.size(); ++i) { + QGraphicsItem *item = childList.at(i); + if (item->flags() & QGraphicsItem::ItemStacksBehindParent) + climbTree(childList.at(i), stackingOrder); + } + } else { + item->d_ptr->globalStackingOrder = (*stackingOrder)++; + } +} + +/*! + \internal +*/ +void QGraphicsSceneBspTreeIndexPrivate::_q_updateSortCache() +{ + Q_Q(QGraphicsSceneBspTreeIndex); + _q_updateIndex(); + + if (!sortCacheEnabled || !updatingSortCache) + return; + + updatingSortCache = false; + int stackingOrder = 0; + + QList topLevels; + + for (int i = 0; i < q->items().count(); ++i) { + QGraphicsItem *item = q->items().at(i); + if (item && item->parentItem() == 0) + topLevels << item; + } + + qSort(topLevels.begin(), topLevels.end(), qt_closestLeaf); + for (int i = 0; i < topLevels.size(); ++i) + climbTree(topLevels.at(i), &stackingOrder); +} + +/*! + \internal +*/ +void QGraphicsSceneBspTreeIndexPrivate::invalidateSortCache() +{ + Q_Q(QGraphicsSceneBspTreeIndex); + if (!sortCacheEnabled || updatingSortCache) + return; + + updatingSortCache = true; + QMetaObject::invokeMethod(q, "_q_updateSortCache", Qt::QueuedConnection); +} + +/*! + Returns true if \a item1 is on top of \a item2. + + \internal +*/ +bool QGraphicsSceneBspTreeIndexPrivate::closestItemFirst_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2) +{ + // Siblings? Just check their z-values. + const QGraphicsItemPrivate *d1 = item1->d_ptr; + const QGraphicsItemPrivate *d2 = item2->d_ptr; + if (d1->parent == d2->parent) + return qt_closestLeaf(item1, item2); + + // Find common ancestor, and each item's ancestor closest to the common + // ancestor. + int item1Depth = d1->depth; + int item2Depth = d2->depth; + const QGraphicsItem *p = item1; + const QGraphicsItem *t1 = item1; + while (item1Depth > item2Depth && (p = p->d_ptr->parent)) { + if (p == item2) { + // item2 is one of item1's ancestors; item1 is on top + return !(t1->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent); + } + t1 = p; + --item1Depth; + } + p = item2; + const QGraphicsItem *t2 = item2; + while (item2Depth > item1Depth && (p = p->d_ptr->parent)) { + if (p == item1) { + // item1 is one of item2's ancestors; item1 is not on top + return (t2->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent); + } + t2 = p; + --item2Depth; + } + + // item1Ancestor is now at the same level as item2Ancestor, but not the same. + const QGraphicsItem *a1 = t1; + const QGraphicsItem *a2 = t2; + while (a1) { + const QGraphicsItem *p1 = a1; + const QGraphicsItem *p2 = a2; + a1 = a1->parentItem(); + a2 = a2->parentItem(); + if (a1 && a1 == a2) + return qt_closestLeaf(p1, p2); + } + + // No common ancestor? Then just compare the items' toplevels directly. + return qt_closestLeaf(t1->topLevelItem(), t2->topLevelItem()); +} + +/*! + Returns true if \a item2 is on top of \a item1. + + \internal +*/ +bool QGraphicsSceneBspTreeIndexPrivate::closestItemLast_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2) +{ + return closestItemFirst_withoutCache(item2, item1); +} + +/*! + Sort a list of \a itemList in a specific \a order and use the cache if requested. + + \internal +*/ +void QGraphicsSceneBspTreeIndexPrivate::sortItems(QList *itemList, Qt::SortOrder order, + bool sortCacheEnabled) +{ + if (sortCacheEnabled) { + if (order == Qt::AscendingOrder) { + qSort(itemList->begin(), itemList->end(), closestItemFirst_withCache); + } else if (order == Qt::DescendingOrder) { + qSort(itemList->begin(), itemList->end(), closestItemLast_withCache); + } + } else { + if (order == Qt::AscendingOrder) { + qSort(itemList->begin(), itemList->end(), closestItemFirst_withoutCache); + } else if (order == Qt::DescendingOrder) { + qSort(itemList->begin(), itemList->end(), closestItemLast_withoutCache); + } + } +} + +/*! + Constructs a BSP scene index for the given \a scene. +*/ +QGraphicsSceneBspTreeIndex::QGraphicsSceneBspTreeIndex(QGraphicsScene *scene) + : QGraphicsSceneIndex(*new QGraphicsSceneBspTreeIndexPrivate(scene), scene) +{ + +} + +/*! + \reimp + Return the rect indexed by the BSP index. +*/ +QRectF QGraphicsSceneBspTreeIndex::indexedRect() const +{ + Q_D(const QGraphicsSceneBspTreeIndex); + const_cast(d)->_q_updateIndex(); + return scene()->d_func()->hasSceneRect ? scene()->d_func()->sceneRect : scene()->d_func()->growingItemsBoundingRect; +} + +/*! + \reimp + Clear the all the BSP index. +*/ +void QGraphicsSceneBspTreeIndex::clear() +{ + Q_D(QGraphicsSceneBspTreeIndex); + d->bsp.clear(); + d->lastItemCount = 0; + d->freeItemIndexes.clear(); + d->indexedItems.clear(); + d->unindexedItems.clear(); +} + +/*! + Add the \a item into the BSP index. +*/ +void QGraphicsSceneBspTreeIndex::addItem(QGraphicsItem *item) +{ + Q_D(QGraphicsSceneBspTreeIndex); + // Prevent reusing a recently deleted pointer: purge all removed items + // from our lists. + d->purgeRemovedItems(); + + // Invalidate any sort caching; arrival of a new item means we need to + // resort. + // Update the scene's sort cache settings. + item->d_ptr->globalStackingOrder = -1; + d->invalidateSortCache(); + + // Indexing requires sceneBoundingRect(), but because \a item might + // not be completely constructed at this point, we need to store it in + // a temporary list and schedule an indexing for later. + d->unindexedItems << item; + item->d_func()->index = -1; + d->startIndexTimer(0); +} + +/*! + This really add the item in the BSP. + \internal +*/ +void QGraphicsSceneBspTreeIndexPrivate::addToIndex(QGraphicsItem *item) +{ + if (item->d_func()->index != -1) { + bsp.insertItem(item, item->sceneBoundingRect()); + foreach (QGraphicsItem *child, item->children()) + child->addToIndex(); + } else { + // The BSP tree is regenerated if the number of items grows to a + // certain threshold, or if the bounding rect of the graph doubles in + // size. + startIndexTimer(); + } +} + +/*! + Remove the \a item from the BSP index. +*/ +void QGraphicsSceneBspTreeIndex::removeItem(QGraphicsItem *item) +{ + Q_D(QGraphicsSceneBspTreeIndex); + // Note: This will access item's sceneBoundingRect(), which (as this is + // C++) is why we cannot call removeItem() from QGraphicsItem's + // destructor. + d->removeFromIndex(item); + + // Invalidate any sort caching; arrival of a new item means we need to + // resort. + d->invalidateSortCache(); + + // Remove from our item lists. + int index = item->d_func()->index; + if (index != -1) { + d->freeItemIndexes << index; + d->indexedItems[index] = 0; + } else { + d->unindexedItems.removeAll(item); + } +} + +/*! + \reimp + Delete the \a item from the BSP index (without accessing its boundingRect). +*/ +void QGraphicsSceneBspTreeIndex::deleteItem(QGraphicsItem *item) +{ + Q_D(QGraphicsSceneBspTreeIndex); + // Invalidate any sort caching; arrival of a new item means we need to + // resort. + d->invalidateSortCache(); + + int index = item->d_func()->index; + if (index != -1) { + // Important: The index is useless until purgeRemovedItems() is + // called. + d->indexedItems[index] = (QGraphicsItem *)0; + if (!d->purgePending) { + d->purgePending = true; + scene()->update(); + } + d->removedItems << item; + } else { + // Recently added items are purged immediately. unindexedItems() never + // contains stale items. + d->unindexedItems.removeAll(item); + scene()->update(); + } +} + +/*! + Really remove the item from the BSP + \internal +*/ +void QGraphicsSceneBspTreeIndexPrivate::removeFromIndex(QGraphicsItem *item) +{ + if (item->d_func()->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) { + // ### remove from child index only if applicable + return; + } + int index = item->d_func()->index; + if (index != -1) { + bsp.removeItem(item, item->sceneBoundingRect()); + freeItemIndexes << index; + indexedItems[index] = 0; + item->d_func()->index = -1; + unindexedItems << item; + + //prepareGeometryChange will call prepareBoundingRectChange + foreach (QGraphicsItem *child, item->children()) + child->prepareGeometryChange(); + } + startIndexTimer(); +} + +/*! + \reimp + Update the BSP when the \a item 's bounding rect has changed. +*/ +void QGraphicsSceneBspTreeIndex::prepareBoundingRectChange(const QGraphicsItem *item) +{ + Q_D(QGraphicsSceneBspTreeIndex); + // Note: This will access item's sceneBoundingRect(), which (as this is + // C++) is why we cannot call removeItem() from QGraphicsItem's + // destructor. + d->removeFromIndex(const_cast(item)); +} + +/*! + Returns an estimation visible items that are either inside or + intersect with the specified \a rect and return a list sorted using \a order. + + \a deviceTransform is the transformation apply to the view. + +*/ +QList QGraphicsSceneBspTreeIndex::estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const +{ + Q_D(const QGraphicsSceneBspTreeIndex); + const_cast(d)->purgeRemovedItems(); + const_cast(d)->_q_updateSortCache(); + + QList rectItems = d->bsp.items(rect); + // Fill in with any unindexed items + for (int i = 0; i < d->unindexedItems.size(); ++i) { + if (QGraphicsItem *item = d->unindexedItems.at(i)) { + if (!item->d_ptr->itemDiscovered && item->d_ptr->visible && !(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) { + QRectF boundingRect = item->sceneBoundingRect(); + if (QRectF_intersects(boundingRect, rect)) { + item->d_ptr->itemDiscovered = 1; + rectItems << item; + } + } + } + } + + // Reset the discovered state of all discovered items + for (int i = 0; i < rectItems.size(); ++i) + rectItems.at(i)->d_func()->itemDiscovered = 0; + + d->sortItems(&rectItems, order, d->sortCacheEnabled); + + return rectItems; +} + + +/*! + \fn QList QGraphicsSceneBspTreeIndex::items(Qt::SortOrder order = Qt::AscendingOrder) const; + + Return all items in the BSP index and sort them using \a order. +*/ +QList QGraphicsSceneBspTreeIndex::items(Qt::SortOrder order) const +{ + Q_D(const QGraphicsSceneBspTreeIndex); + const_cast(d)->purgeRemovedItems(); + QList itemList; + // If freeItemIndexes is empty, we know there are no holes in indexedItems and + // unindexedItems. + if (d->freeItemIndexes.isEmpty()) { + if (d->unindexedItems.isEmpty()) { + itemList = d->indexedItems; + } else { + itemList = d->indexedItems + d->unindexedItems; + } + } else { + // Rebuild the list of items to avoid holes. ### We could also just + // compress the item lists at this point. + foreach (QGraphicsItem *item, d->indexedItems + d->unindexedItems) { + if (item) + itemList << item; + } + } + if (order != -1) { + //We sort descending order + d->sortItems(&itemList, order, d->sortCacheEnabled); + } + return itemList; +} + +/*! + \property QGraphicsSceneBspTreeIndex::bspTreeDepth + \brief the depth of the BSP index tree + \since 4.6 + + This value determines the depth of BSP tree. The depth + directly affects performance and memory usage; the latter + growing exponentially with the depth of the tree. With an optimal tree + depth, the index can instantly determine the locality of items, even + for scenes with thousands or millions of items. This also greatly improves + rendering performance. + + By default, the value is 0, in which case Qt will guess a reasonable + default depth based on the size, location and number of items in the + scene. If these parameters change frequently, however, you may experience + slowdowns as the index retunes the depth internally. You can avoid + potential slowdowns by fixating the tree depth through setting this + property. + + The depth of the tree and the size of the scene rectangle decide the + granularity of the scene's partitioning. The size of each scene segment is + determined by the following algorithm: + + The BSP tree has an optimal size when each segment contains between 0 and + 10 items. + +*/ +int QGraphicsSceneBspTreeIndex::bspTreeDepth() +{ + Q_D(const QGraphicsSceneBspTreeIndex); + return d->bspTreeDepth; +} + +void QGraphicsSceneBspTreeIndex::setBspTreeDepth(int depth) +{ + Q_D(QGraphicsSceneBspTreeIndex); + d->bspTreeDepth = depth; + d->resetIndex(); +} + +/*! + \reimp + + This method react to the \a rect change of the scene and + reset the BSP tree index. +*/ +void QGraphicsSceneBspTreeIndex::sceneRectChanged(const QRectF &rect) +{ + Q_D(QGraphicsSceneBspTreeIndex); + d->sceneRect = rect; + d->resetIndex(); +} + +/*! + \reimp + + This method react to the \a change of the \a item and use the \a value to + update the BSP tree if necessary. + +*/ +void QGraphicsSceneBspTreeIndex::itemChanged(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value) +{ + Q_D(QGraphicsSceneBspTreeIndex); + switch (change) { + case QGraphicsItem::ItemZValueChange: + case QGraphicsItem::ItemParentChange: { + d->invalidateSortCache(); + break; + } + default: + break; + } + return QGraphicsSceneIndex::itemChanged(item, change, value); +} +/*! + \reimp + + Used to catch the timer event. + + \internal +*/ +bool QGraphicsSceneBspTreeIndex::event(QEvent *event) +{ + Q_D(QGraphicsSceneBspTreeIndex); + switch (event->type()) { + case QEvent::Timer: + if (d->indexTimerId && static_cast(event)->timerId() == d->indexTimerId) { + if (d->restartIndexTimer) { + d->restartIndexTimer = false; + } else { + // this call will kill the timer + d->_q_updateIndex(); + } + } + // Fallthrough intended - support timers in subclasses. + default: + return QObject::event(event); + } + return true; +} + +QT_END_NAMESPACE + +#include "moc_qgraphicsscenebsptreeindex.cpp" + +#endif // QT_NO_GRAPHICSVIEW + diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex.h new file mode 100644 index 0000000..0444a30 --- /dev/null +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.h @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header +// file may change from version to version without notice, or even be removed. +// +// We mean it. +// + +#ifndef QGRAPHICSBSPTREEINDEX_H +#define QGRAPHICSBSPTREEINDEX_H + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW + +#include +#include +#include +#include +#include + +#include "qgraphicsscene_bsp_p.h" + +class QGraphicsSceneBspTreeIndexPrivate; + +class Q_AUTOTEST_EXPORT QGraphicsSceneBspTreeIndex : public QGraphicsSceneIndex +{ + Q_OBJECT + Q_PROPERTY(int bspTreeDepth READ bspTreeDepth WRITE setBspTreeDepth) +public: + QGraphicsSceneBspTreeIndex(QGraphicsScene *scene = 0); + QRectF indexedRect() const; + + QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const; + + QList items(Qt::SortOrder order = Qt::AscendingOrder) const; + + int bspTreeDepth(); + void setBspTreeDepth(int depth); + +protected: + bool event(QEvent *event); + void clear(); + + void addItem(QGraphicsItem *item); + void removeItem(QGraphicsItem *item); + void deleteItem(QGraphicsItem *item); + void prepareBoundingRectChange(const QGraphicsItem *item); + + void sceneRectChanged(const QRectF &rect); + void itemChanged(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value); + +private : + Q_DECLARE_PRIVATE(QGraphicsSceneBspTreeIndex) + Q_DISABLE_COPY(QGraphicsSceneBspTreeIndex) + Q_PRIVATE_SLOT(d_func(), void _q_updateSortCache()) + Q_PRIVATE_SLOT(d_func(), void _q_updateIndex()) + + friend class QGraphicsScene; + friend class QGraphicsScenePrivate; +}; + +#endif // QT_NO_GRAPHICSVIEW + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QGRAPHICSBSPTREEINDEX_H diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp deleted file mode 100644 index b19248a..0000000 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp +++ /dev/null @@ -1,760 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! - \class QGraphicsSceneBspTreeIndex - \brief The QGraphicsSceneBspTreeIndex class provides an implementation of - a BSP indexing algorithm for discovering items in QGraphicsScene. - \since 4.6 - \ingroup multimedia - \ingroup graphicsview-api - \mainclass - - QGraphicsSceneBspTreeIndex index use a BSP(Binary Space Partitioning) - implementation to discover items quickly. This implementation is - very efficient for static scene. It has a depth that you can set. - The depth directly affects performance and memory usage; the latter - growing exponentially with the depth of the tree. With an optimal tree - depth, the index can instantly determine the locality of items, even - for scenes with thousands or millions of items. This also greatly improves - rendering performance. - - By default, the value is 0, in which case Qt will guess a reasonable - default depth based on the size, location and number of items in the - scene. If these parameters change frequently, however, you may experience - slowdowns as the index retunes the depth internally. You can avoid - potential slowdowns by fixating the tree depth through setting this - property. - - The depth of the tree and the size of the scene rectangle decide the - granularity of the scene's partitioning. The size of each scene segment is - determined by the following algorithm: - - The BSP tree has an optimal size when each segment contains between 0 and - 10 items. - - \sa QGraphicsScene, QGraphicsView, QGraphicsSceneIndex -*/ - -#include "qgraphicsscenebsptreeindex_p.h" - -#ifndef QT_NO_GRAPHICSVIEW - -#include "qgraphicsscenebsptreeindex_p_p.h" -#include "qgraphicssceneindex_p.h" -#include "qgraphicsitem_p.h" -#include "qgraphicsscene_p.h" - -#include - -#include - -QT_BEGIN_NAMESPACE - -static inline int intmaxlog(int n) -{ - return (n > 0 ? qMax(qCeil(qLn(qreal(n)) / qLn(qreal(2))), 5) : 0); -} - -/*! - Constructs a private scene bsp index. -*/ -QGraphicsSceneBspTreeIndexPrivate::QGraphicsSceneBspTreeIndexPrivate(QGraphicsScene *scene) - : QGraphicsSceneIndexPrivate(scene), - bspTreeDepth(0), - indexTimerId(0), - restartIndexTimer(false), - regenerateIndex(true), - lastItemCount(0), - purgePending(false), - sortCacheEnabled(false), - updatingSortCache(false) -{ -} - - -/*! - This method will update the BSP index by removing the items from the temporary - unindexed list and add them in the indexedItems list. This will also - update the growingItemsBoundingRect if needed. This will update the BSP - implementation as well. - - \internal -*/ -void QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex() -{ - Q_Q(QGraphicsSceneBspTreeIndex); - if (!indexTimerId) - return; - - QGraphicsScenePrivate * scenePrivate = q->scene()->d_func(); - q->killTimer(indexTimerId); - indexTimerId = 0; - - purgeRemovedItems(); - - // Add unindexedItems to indexedItems - QRectF unindexedItemsBoundingRect; - for (int i = 0; i < unindexedItems.size(); ++i) { - if (QGraphicsItem *item = unindexedItems.at(i)) { - unindexedItemsBoundingRect |= item->sceneBoundingRect(); - if (!freeItemIndexes.isEmpty()) { - int freeIndex = freeItemIndexes.takeFirst(); - item->d_func()->index = freeIndex; - indexedItems[freeIndex] = item; - } else { - item->d_func()->index = indexedItems.size(); - indexedItems << item; - } - } - } - - // Update growing scene rect. - QRectF oldGrowingItemsBoundingRect = scenePrivate->growingItemsBoundingRect; - scenePrivate->growingItemsBoundingRect |= unindexedItemsBoundingRect; - - // Determine whether we should regenerate the BSP tree. - if (bspTreeDepth == 0) { - int oldDepth = intmaxlog(lastItemCount); - bspTreeDepth = intmaxlog(indexedItems.size()); - static const int slack = 100; - if (bsp.leafCount() == 0 || (oldDepth != bspTreeDepth && qAbs(lastItemCount - indexedItems.size()) > slack)) { - // ### Crude algorithm. - regenerateIndex = true; - } - } - - // Regenerate the tree. - if (regenerateIndex) { - regenerateIndex = false; - bsp.initialize(q->scene()->sceneRect(), bspTreeDepth); - unindexedItems = indexedItems; - lastItemCount = indexedItems.size(); - q->scene()->update(); - - // Take this opportunity to reset our largest-item counter for - // untransformable items. When the items are inserted into the BSP - // tree, we'll get an accurate calculation. - scenePrivate->largestUntransformableItem = QRectF(); - } - - // Insert all unindexed items into the tree. - for (int i = 0; i < unindexedItems.size(); ++i) { - if (QGraphicsItem *item = unindexedItems.at(i)) { - QRectF rect = item->sceneBoundingRect(); - if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) - continue; - - bsp.insertItem(item, rect); - - // If the item ignores view transformations, update our - // largest-item-counter to ensure that the view can accurately - // discover untransformable items when drawing. - if (item->d_ptr->itemIsUntransformable()) { - QGraphicsItem *topmostUntransformable = item; - while (topmostUntransformable && (topmostUntransformable->d_ptr->ancestorFlags - & QGraphicsItemPrivate::AncestorIgnoresTransformations)) { - topmostUntransformable = topmostUntransformable->parentItem(); - } - // ### Verify that this is the correct largest untransformable rectangle. - scenePrivate->largestUntransformableItem |= item->mapToItem(topmostUntransformable, item->boundingRect()).boundingRect(); - } - } - } - unindexedItems.clear(); - - // Notify scene rect changes. - if (!scenePrivate->hasSceneRect && scenePrivate->growingItemsBoundingRect != oldGrowingItemsBoundingRect) - emit q->scene()->sceneRectChanged(scenePrivate->growingItemsBoundingRect); -} - - -/*! - \internal - - Removes stale pointers from all data structures. -*/ -void QGraphicsSceneBspTreeIndexPrivate::purgeRemovedItems() -{ - if (!purgePending && removedItems.isEmpty()) - return; - - // Remove stale items from the BSP tree. - bsp.removeItems(removedItems); - // Purge this list. - removedItems.clear(); - freeItemIndexes.clear(); - for (int i = 0; i < indexedItems.size(); ++i) { - if (!indexedItems.at(i)) - freeItemIndexes << i; - } - purgePending = false; -} - -/*! - \internal - - Starts or restarts the timer used for reindexing unindexed items. -*/ -void QGraphicsSceneBspTreeIndexPrivate::startIndexTimer(int interval) -{ - Q_Q(QGraphicsSceneBspTreeIndex); - if (indexTimerId) { - restartIndexTimer = true; - } else { - indexTimerId = q->startTimer(interval); - } -} - -/*! - \internal -*/ -void QGraphicsSceneBspTreeIndexPrivate::resetIndex() -{ - purgeRemovedItems(); - for (int i = 0; i < indexedItems.size(); ++i) { - if (QGraphicsItem *item = indexedItems.at(i)) { - item->d_ptr->index = -1; - unindexedItems << item; - } - } - indexedItems.clear(); - freeItemIndexes.clear(); - regenerateIndex = true; - startIndexTimer(); -} - -/*! - \internal -*/ -void QGraphicsSceneBspTreeIndexPrivate::climbTree(QGraphicsItem *item, int *stackingOrder) -{ - if (!item->d_ptr->children.isEmpty()) { - QList childList = item->d_ptr->children; - qSort(childList.begin(), childList.end(), qt_closestLeaf); - for (int i = 0; i < childList.size(); ++i) { - QGraphicsItem *item = childList.at(i); - if (!(item->flags() & QGraphicsItem::ItemStacksBehindParent)) - climbTree(childList.at(i), stackingOrder); - } - item->d_ptr->globalStackingOrder = (*stackingOrder)++; - for (int i = 0; i < childList.size(); ++i) { - QGraphicsItem *item = childList.at(i); - if (item->flags() & QGraphicsItem::ItemStacksBehindParent) - climbTree(childList.at(i), stackingOrder); - } - } else { - item->d_ptr->globalStackingOrder = (*stackingOrder)++; - } -} - -/*! - \internal -*/ -void QGraphicsSceneBspTreeIndexPrivate::_q_updateSortCache() -{ - Q_Q(QGraphicsSceneBspTreeIndex); - _q_updateIndex(); - - if (!sortCacheEnabled || !updatingSortCache) - return; - - updatingSortCache = false; - int stackingOrder = 0; - - QList topLevels; - - for (int i = 0; i < q->items().count(); ++i) { - QGraphicsItem *item = q->items().at(i); - if (item && item->parentItem() == 0) - topLevels << item; - } - - qSort(topLevels.begin(), topLevels.end(), qt_closestLeaf); - for (int i = 0; i < topLevels.size(); ++i) - climbTree(topLevels.at(i), &stackingOrder); -} - -/*! - \internal -*/ -void QGraphicsSceneBspTreeIndexPrivate::invalidateSortCache() -{ - Q_Q(QGraphicsSceneBspTreeIndex); - if (!sortCacheEnabled || updatingSortCache) - return; - - updatingSortCache = true; - QMetaObject::invokeMethod(q, "_q_updateSortCache", Qt::QueuedConnection); -} - -/*! - Returns true if \a item1 is on top of \a item2. - - \internal -*/ -bool QGraphicsSceneBspTreeIndexPrivate::closestItemFirst_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2) -{ - // Siblings? Just check their z-values. - const QGraphicsItemPrivate *d1 = item1->d_ptr; - const QGraphicsItemPrivate *d2 = item2->d_ptr; - if (d1->parent == d2->parent) - return qt_closestLeaf(item1, item2); - - // Find common ancestor, and each item's ancestor closest to the common - // ancestor. - int item1Depth = d1->depth; - int item2Depth = d2->depth; - const QGraphicsItem *p = item1; - const QGraphicsItem *t1 = item1; - while (item1Depth > item2Depth && (p = p->d_ptr->parent)) { - if (p == item2) { - // item2 is one of item1's ancestors; item1 is on top - return !(t1->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent); - } - t1 = p; - --item1Depth; - } - p = item2; - const QGraphicsItem *t2 = item2; - while (item2Depth > item1Depth && (p = p->d_ptr->parent)) { - if (p == item1) { - // item1 is one of item2's ancestors; item1 is not on top - return (t2->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent); - } - t2 = p; - --item2Depth; - } - - // item1Ancestor is now at the same level as item2Ancestor, but not the same. - const QGraphicsItem *a1 = t1; - const QGraphicsItem *a2 = t2; - while (a1) { - const QGraphicsItem *p1 = a1; - const QGraphicsItem *p2 = a2; - a1 = a1->parentItem(); - a2 = a2->parentItem(); - if (a1 && a1 == a2) - return qt_closestLeaf(p1, p2); - } - - // No common ancestor? Then just compare the items' toplevels directly. - return qt_closestLeaf(t1->topLevelItem(), t2->topLevelItem()); -} - -/*! - Returns true if \a item2 is on top of \a item1. - - \internal -*/ -bool QGraphicsSceneBspTreeIndexPrivate::closestItemLast_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2) -{ - return closestItemFirst_withoutCache(item2, item1); -} - -/*! - Sort a list of \a itemList in a specific \a order and use the cache if requested. - - \internal -*/ -void QGraphicsSceneBspTreeIndexPrivate::sortItems(QList *itemList, Qt::SortOrder order, - bool sortCacheEnabled) -{ - if (sortCacheEnabled) { - if (order == Qt::AscendingOrder) { - qSort(itemList->begin(), itemList->end(), closestItemFirst_withCache); - } else if (order == Qt::DescendingOrder) { - qSort(itemList->begin(), itemList->end(), closestItemLast_withCache); - } - } else { - if (order == Qt::AscendingOrder) { - qSort(itemList->begin(), itemList->end(), closestItemFirst_withoutCache); - } else if (order == Qt::DescendingOrder) { - qSort(itemList->begin(), itemList->end(), closestItemLast_withoutCache); - } - } -} - -/*! - Constructs a BSP scene index for the given \a scene. -*/ -QGraphicsSceneBspTreeIndex::QGraphicsSceneBspTreeIndex(QGraphicsScene *scene) - : QGraphicsSceneIndex(*new QGraphicsSceneBspTreeIndexPrivate(scene), scene) -{ - -} - -/*! - \reimp - Return the rect indexed by the BSP index. -*/ -QRectF QGraphicsSceneBspTreeIndex::indexedRect() const -{ - Q_D(const QGraphicsSceneBspTreeIndex); - const_cast(d)->_q_updateIndex(); - return scene()->d_func()->hasSceneRect ? scene()->d_func()->sceneRect : scene()->d_func()->growingItemsBoundingRect; -} - -/*! - \reimp - Clear the all the BSP index. -*/ -void QGraphicsSceneBspTreeIndex::clear() -{ - Q_D(QGraphicsSceneBspTreeIndex); - d->bsp.clear(); - d->lastItemCount = 0; - d->freeItemIndexes.clear(); - d->indexedItems.clear(); - d->unindexedItems.clear(); -} - -/*! - Add the \a item into the BSP index. -*/ -void QGraphicsSceneBspTreeIndex::addItem(QGraphicsItem *item) -{ - Q_D(QGraphicsSceneBspTreeIndex); - // Prevent reusing a recently deleted pointer: purge all removed items - // from our lists. - d->purgeRemovedItems(); - - // Invalidate any sort caching; arrival of a new item means we need to - // resort. - // Update the scene's sort cache settings. - item->d_ptr->globalStackingOrder = -1; - d->invalidateSortCache(); - - // Indexing requires sceneBoundingRect(), but because \a item might - // not be completely constructed at this point, we need to store it in - // a temporary list and schedule an indexing for later. - d->unindexedItems << item; - item->d_func()->index = -1; - d->startIndexTimer(0); -} - -/*! - This really add the item in the BSP. - \internal -*/ -void QGraphicsSceneBspTreeIndexPrivate::addToIndex(QGraphicsItem *item) -{ - if (item->d_func()->index != -1) { - bsp.insertItem(item, item->sceneBoundingRect()); - foreach (QGraphicsItem *child, item->children()) - child->addToIndex(); - } else { - // The BSP tree is regenerated if the number of items grows to a - // certain threshold, or if the bounding rect of the graph doubles in - // size. - startIndexTimer(); - } -} - -/*! - Remove the \a item from the BSP index. -*/ -void QGraphicsSceneBspTreeIndex::removeItem(QGraphicsItem *item) -{ - Q_D(QGraphicsSceneBspTreeIndex); - // Note: This will access item's sceneBoundingRect(), which (as this is - // C++) is why we cannot call removeItem() from QGraphicsItem's - // destructor. - d->removeFromIndex(item); - - // Invalidate any sort caching; arrival of a new item means we need to - // resort. - d->invalidateSortCache(); - - // Remove from our item lists. - int index = item->d_func()->index; - if (index != -1) { - d->freeItemIndexes << index; - d->indexedItems[index] = 0; - } else { - d->unindexedItems.removeAll(item); - } -} - -/*! - \reimp - Delete the \a item from the BSP index (without accessing its boundingRect). -*/ -void QGraphicsSceneBspTreeIndex::deleteItem(QGraphicsItem *item) -{ - Q_D(QGraphicsSceneBspTreeIndex); - // Invalidate any sort caching; arrival of a new item means we need to - // resort. - d->invalidateSortCache(); - - int index = item->d_func()->index; - if (index != -1) { - // Important: The index is useless until purgeRemovedItems() is - // called. - d->indexedItems[index] = (QGraphicsItem *)0; - if (!d->purgePending) { - d->purgePending = true; - scene()->update(); - } - d->removedItems << item; - } else { - // Recently added items are purged immediately. unindexedItems() never - // contains stale items. - d->unindexedItems.removeAll(item); - scene()->update(); - } -} - -/*! - Really remove the item from the BSP - \internal -*/ -void QGraphicsSceneBspTreeIndexPrivate::removeFromIndex(QGraphicsItem *item) -{ - if (item->d_func()->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) { - // ### remove from child index only if applicable - return; - } - int index = item->d_func()->index; - if (index != -1) { - bsp.removeItem(item, item->sceneBoundingRect()); - freeItemIndexes << index; - indexedItems[index] = 0; - item->d_func()->index = -1; - unindexedItems << item; - - //prepareGeometryChange will call prepareBoundingRectChange - foreach (QGraphicsItem *child, item->children()) - child->prepareGeometryChange(); - } - startIndexTimer(); -} - -/*! - \reimp - Update the BSP when the \a item 's bounding rect has changed. -*/ -void QGraphicsSceneBspTreeIndex::prepareBoundingRectChange(const QGraphicsItem *item) -{ - Q_D(QGraphicsSceneBspTreeIndex); - // Note: This will access item's sceneBoundingRect(), which (as this is - // C++) is why we cannot call removeItem() from QGraphicsItem's - // destructor. - d->removeFromIndex(const_cast(item)); -} - -/*! - Returns an estimation visible items that are either inside or - intersect with the specified \a rect and return a list sorted using \a order. - - \a deviceTransform is the transformation apply to the view. - -*/ -QList QGraphicsSceneBspTreeIndex::estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const -{ - Q_D(const QGraphicsSceneBspTreeIndex); - const_cast(d)->purgeRemovedItems(); - const_cast(d)->_q_updateSortCache(); - - QList rectItems = d->bsp.items(rect); - // Fill in with any unindexed items - for (int i = 0; i < d->unindexedItems.size(); ++i) { - if (QGraphicsItem *item = d->unindexedItems.at(i)) { - if (!item->d_ptr->itemDiscovered && item->d_ptr->visible && !(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) { - QRectF boundingRect = item->sceneBoundingRect(); - if (QRectF_intersects(boundingRect, rect)) { - item->d_ptr->itemDiscovered = 1; - rectItems << item; - } - } - } - } - - // Reset the discovered state of all discovered items - for (int i = 0; i < rectItems.size(); ++i) - rectItems.at(i)->d_func()->itemDiscovered = 0; - - d->sortItems(&rectItems, order, d->sortCacheEnabled); - - return rectItems; -} - - -/*! - \fn QList QGraphicsSceneBspTreeIndex::items(Qt::SortOrder order = Qt::AscendingOrder) const; - - Return all items in the BSP index and sort them using \a order. -*/ -QList QGraphicsSceneBspTreeIndex::items(Qt::SortOrder order) const -{ - Q_D(const QGraphicsSceneBspTreeIndex); - const_cast(d)->purgeRemovedItems(); - QList itemList; - // If freeItemIndexes is empty, we know there are no holes in indexedItems and - // unindexedItems. - if (d->freeItemIndexes.isEmpty()) { - if (d->unindexedItems.isEmpty()) { - itemList = d->indexedItems; - } else { - itemList = d->indexedItems + d->unindexedItems; - } - } else { - // Rebuild the list of items to avoid holes. ### We could also just - // compress the item lists at this point. - foreach (QGraphicsItem *item, d->indexedItems + d->unindexedItems) { - if (item) - itemList << item; - } - } - if (order != -1) { - //We sort descending order - d->sortItems(&itemList, order, d->sortCacheEnabled); - } - return itemList; -} - -/*! - \property QGraphicsSceneBspTreeIndex::bspTreeDepth - \brief the depth of the BSP index tree - \since 4.6 - - This value determines the depth of BSP tree. The depth - directly affects performance and memory usage; the latter - growing exponentially with the depth of the tree. With an optimal tree - depth, the index can instantly determine the locality of items, even - for scenes with thousands or millions of items. This also greatly improves - rendering performance. - - By default, the value is 0, in which case Qt will guess a reasonable - default depth based on the size, location and number of items in the - scene. If these parameters change frequently, however, you may experience - slowdowns as the index retunes the depth internally. You can avoid - potential slowdowns by fixating the tree depth through setting this - property. - - The depth of the tree and the size of the scene rectangle decide the - granularity of the scene's partitioning. The size of each scene segment is - determined by the following algorithm: - - The BSP tree has an optimal size when each segment contains between 0 and - 10 items. - -*/ -int QGraphicsSceneBspTreeIndex::bspTreeDepth() -{ - Q_D(const QGraphicsSceneBspTreeIndex); - return d->bspTreeDepth; -} - -void QGraphicsSceneBspTreeIndex::setBspTreeDepth(int depth) -{ - Q_D(QGraphicsSceneBspTreeIndex); - d->bspTreeDepth = depth; - d->resetIndex(); -} - -/*! - \reimp - - This method react to the \a rect change of the scene and - reset the BSP tree index. -*/ -void QGraphicsSceneBspTreeIndex::sceneRectChanged(const QRectF &rect) -{ - Q_D(QGraphicsSceneBspTreeIndex); - d->sceneRect = rect; - d->resetIndex(); -} - -/*! - \reimp - - This method react to the \a change of the \a item and use the \a value to - update the BSP tree if necessary. - -*/ -void QGraphicsSceneBspTreeIndex::itemChanged(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value) -{ - Q_D(QGraphicsSceneBspTreeIndex); - switch (change) { - case QGraphicsItem::ItemZValueChange: - case QGraphicsItem::ItemParentChange: { - d->invalidateSortCache(); - break; - } - default: - break; - } - return QGraphicsSceneIndex::itemChanged(item, change, value); -} -/*! - \reimp - - Used to catch the timer event. - - \internal -*/ -bool QGraphicsSceneBspTreeIndex::event(QEvent *event) -{ - Q_D(QGraphicsSceneBspTreeIndex); - switch (event->type()) { - case QEvent::Timer: - if (d->indexTimerId && static_cast(event)->timerId() == d->indexTimerId) { - if (d->restartIndexTimer) { - d->restartIndexTimer = false; - } else { - // this call will kill the timer - d->_q_updateIndex(); - } - } - // Fallthrough intended - support timers in subclasses. - default: - return QObject::event(event); - } - return true; -} - -QT_END_NAMESPACE - -#include "moc_qgraphicsscenebsptreeindex_p.cpp" - -#endif // QT_NO_GRAPHICSVIEW - diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h index 40b8f0b..6bafbc8 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h @@ -39,63 +39,112 @@ ** ****************************************************************************/ -#include - -#ifndef QGRAPHICSBSPTREEINDEX_H -#define QGRAPHICSBSPTREEINDEX_H +#ifndef QGRAPHICSSCENEBSPTREEINDEX_P_H +#define QGRAPHICSSCENEBSPTREEINDEX_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header +// file may change from version to version without notice, or even be removed. +// +// We mean it. +// + +#include "qgraphicsscenebsptreeindex.h" #if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW +#include +#include + QT_BEGIN_NAMESPACE -#include -#include -#include -#include -#include +static const int QGRAPHICSSCENE_INDEXTIMER_TIMEOUT = 2000; -#include "qgraphicsscene_bsp_p.h" +class QGraphicsScene; -class QGraphicsSceneBspTreeIndexPrivate; -class Q_AUTOTEST_EXPORT QGraphicsSceneBspTreeIndex : public QGraphicsSceneIndex +class QGraphicsSceneBspTreeIndexPrivate : public QGraphicsSceneIndexPrivate { - Q_OBJECT - Q_PROPERTY(int bspTreeDepth READ bspTreeDepth WRITE setBspTreeDepth) + Q_DECLARE_PUBLIC(QGraphicsSceneBspTreeIndex) public: - QGraphicsSceneBspTreeIndex(QGraphicsScene *scene = 0); - QRectF indexedRect() const; - - QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const; - - QList items(Qt::SortOrder order = Qt::AscendingOrder) const; - - int bspTreeDepth(); - void setBspTreeDepth(int depth); - -protected: - bool event(QEvent *event); - void clear(); - - void addItem(QGraphicsItem *item); - void removeItem(QGraphicsItem *item); - void deleteItem(QGraphicsItem *item); - void prepareBoundingRectChange(const QGraphicsItem *item); + QGraphicsSceneBspTreeIndexPrivate(QGraphicsScene *scene); + + QGraphicsSceneBspTree bsp; + QRectF sceneRect; + int bspTreeDepth; + int indexTimerId; + bool restartIndexTimer; + bool regenerateIndex; + int lastItemCount; + + QList indexedItems; + QList unindexedItems; + QList freeItemIndexes; + + bool purgePending; + QSet removedItems; + void purgeRemovedItems(); + + void _q_updateIndex(); + void startIndexTimer(int interval = QGRAPHICSSCENE_INDEXTIMER_TIMEOUT); + void resetIndex(); + + void addToIndex(QGraphicsItem *item); + void removeFromIndex(QGraphicsItem *item); + + void _q_updateSortCache(); + bool sortCacheEnabled; + bool updatingSortCache; + void invalidateSortCache(); + + static void climbTree(QGraphicsItem *item, int *stackingOrder); + static bool closestItemFirst_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2); + static bool closestItemLast_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2); + + static inline bool closestItemFirst_withCache(const QGraphicsItem *item1, const QGraphicsItem *item2) + { + return item1->d_ptr->globalStackingOrder < item2->d_ptr->globalStackingOrder; + } + static inline bool closestItemLast_withCache(const QGraphicsItem *item1, const QGraphicsItem *item2) + { + return item1->d_ptr->globalStackingOrder >= item2->d_ptr->globalStackingOrder; + } + + static void sortItems(QList *itemList, Qt::SortOrder order, bool cached); +}; - void sceneRectChanged(const QRectF &rect); - void itemChanged(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value); -private : - Q_DECLARE_PRIVATE(QGraphicsSceneBspTreeIndex) - Q_DISABLE_COPY(QGraphicsSceneBspTreeIndex) - Q_PRIVATE_SLOT(d_func(), void _q_updateSortCache()) - Q_PRIVATE_SLOT(d_func(), void _q_updateIndex()) +/*! + \internal +*/ +inline bool qt_closestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2) +{ + // Return true if sibling item1 is on top of item2. + const QGraphicsItemPrivate *d1 = item1->d_ptr; + const QGraphicsItemPrivate *d2 = item2->d_ptr; + bool f1 = d1->flags & QGraphicsItem::ItemStacksBehindParent; + bool f2 = d2->flags & QGraphicsItem::ItemStacksBehindParent; + if (f1 != f2) return f2; + qreal z1 = d1->z; + qreal z2 = d2->z; + return z1 > z2; +} + +/*! + \internal +*/ +static inline bool qt_notclosestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2) +{ + return qt_closestLeaf(item2, item1); +} - friend class QGraphicsScene; - friend class QGraphicsScenePrivate; -}; QT_END_NAMESPACE -#endif // QT_NO_GRAPHICSVIEW +#endif // QGRAPHICSSCENEBSPTREEINDEX_P_H + +#endif -#endif // QGRAPHICSBSPTREEINDEX_H diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p_p.h deleted file mode 100644 index 30f6e26..0000000 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p_p.h +++ /dev/null @@ -1,150 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRAPHICSSCENEBSPTREEINDEX_P_P_H -#define QGRAPHICSSCENEBSPTREEINDEX_P_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header -// file may change from version to version without notice, or even be removed. -// -// We mean it. -// - -#include "qgraphicsscenebsptreeindex_p.h" - -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - -#include -#include - -QT_BEGIN_NAMESPACE - -static const int QGRAPHICSSCENE_INDEXTIMER_TIMEOUT = 2000; - -class QGraphicsScene; - -class QGraphicsSceneBspTreeIndexPrivate : public QGraphicsSceneIndexPrivate -{ - Q_DECLARE_PUBLIC(QGraphicsSceneBspTreeIndex) -public: - QGraphicsSceneBspTreeIndexPrivate(QGraphicsScene *scene); - - QGraphicsSceneBspTree bsp; - QRectF sceneRect; - int bspTreeDepth; - int indexTimerId; - bool restartIndexTimer; - bool regenerateIndex; - int lastItemCount; - - QList indexedItems; - QList unindexedItems; - QList freeItemIndexes; - - bool purgePending; - QSet removedItems; - void purgeRemovedItems(); - - void _q_updateIndex(); - void startIndexTimer(int interval = QGRAPHICSSCENE_INDEXTIMER_TIMEOUT); - void resetIndex(); - - void addToIndex(QGraphicsItem *item); - void removeFromIndex(QGraphicsItem *item); - - void _q_updateSortCache(); - bool sortCacheEnabled; - bool updatingSortCache; - void invalidateSortCache(); - - static void climbTree(QGraphicsItem *item, int *stackingOrder); - static bool closestItemFirst_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2); - static bool closestItemLast_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2); - - static inline bool closestItemFirst_withCache(const QGraphicsItem *item1, const QGraphicsItem *item2) - { - return item1->d_ptr->globalStackingOrder < item2->d_ptr->globalStackingOrder; - } - static inline bool closestItemLast_withCache(const QGraphicsItem *item1, const QGraphicsItem *item2) - { - return item1->d_ptr->globalStackingOrder >= item2->d_ptr->globalStackingOrder; - } - - static void sortItems(QList *itemList, Qt::SortOrder order, bool cached); -}; - - -/*! - \internal -*/ -inline bool qt_closestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2) -{ - // Return true if sibling item1 is on top of item2. - const QGraphicsItemPrivate *d1 = item1->d_ptr; - const QGraphicsItemPrivate *d2 = item2->d_ptr; - bool f1 = d1->flags & QGraphicsItem::ItemStacksBehindParent; - bool f2 = d2->flags & QGraphicsItem::ItemStacksBehindParent; - if (f1 != f2) return f2; - qreal z1 = d1->z; - qreal z2 = d2->z; - return z1 > z2; -} - -/*! - \internal -*/ -static inline bool qt_notclosestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2) -{ - return qt_closestLeaf(item2, item1); -} - - -QT_END_NAMESPACE - -#endif // QGRAPHICSSCENEBSPTREEINDEX_P_P_H - -#endif - diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index 05ec28b..966d8fe 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -46,6 +46,7 @@ \ingroup multimedia \ingroup graphicsview-api \mainclass + \internal The QGraphicsSceneIndex class provides a base class to implement a custom indexing algorithm for discovering items in QGraphicsScene. You @@ -57,7 +58,6 @@ #include "qgraphicssceneindex.h" #include "qgraphicssceneindex_p.h" -#include "qgraphicsscenebsptreeindex_p_p.h" #include "qgraphicsscene.h" #include "qgraphicsitem_p.h" #include "qgraphicsscene_p.h" diff --git a/src/gui/graphicsview/qgraphicssceneindex.h b/src/gui/graphicsview/qgraphicssceneindex.h index 084a623..c0e415c 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.h +++ b/src/gui/graphicsview/qgraphicssceneindex.h @@ -42,6 +42,17 @@ #ifndef QGRAPHICSSCENEINDEX_H #define QGRAPHICSSCENEINDEX_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header +// file may change from version to version without notice, or even be removed. +// +// We mean it. +// + #include #include #include @@ -61,7 +72,7 @@ class QRectF; class QPointF; template class QList; -class Q_GUI_EXPORT QGraphicsSceneIndex: public QObject +class Q_AUTOTEST_EXPORT QGraphicsSceneIndex: public QObject { Q_OBJECT diff --git a/src/gui/graphicsview/qgraphicsscenelinearindex.cpp b/src/gui/graphicsview/qgraphicsscenelinearindex.cpp index 1c898bc..5504493 100644 --- a/src/gui/graphicsview/qgraphicsscenelinearindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenelinearindex.cpp @@ -1,4 +1,4 @@ -#include "qgraphicsscenelinearindex_p.h" +#include "qgraphicsscenelinearindex.h" /*! \class QGraphicsSceneLinearIndex @@ -8,6 +8,7 @@ \ingroup multimedia \ingroup graphicsview-api \mainclass + \internal QGraphicsSceneLinearIndex index is default linear implementation to discover items. It basically store all items in a list and return them to the scene. diff --git a/src/gui/graphicsview/qgraphicsscenelinearindex.h b/src/gui/graphicsview/qgraphicsscenelinearindex.h new file mode 100644 index 0000000..b793d98 --- /dev/null +++ b/src/gui/graphicsview/qgraphicsscenelinearindex.h @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGRAPHICSSCENELINEARINDEX_H +#define QGRAPHICSSCENELINEARINDEX_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW + +#include +#include +#include +#include + +class Q_AUTOTEST_EXPORT QGraphicsSceneLinearIndex : public QGraphicsSceneIndex +{ + Q_OBJECT + +public: + QGraphicsSceneLinearIndex(QGraphicsScene *scene = 0): QGraphicsSceneIndex(scene) + { + } + + QList items(Qt::SortOrder order = Qt::AscendingOrder) const { + Q_UNUSED(order); + return m_items; + } + + virtual QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const { + Q_UNUSED(rect); + Q_UNUSED(order); + Q_UNUSED(deviceTransform); + return m_items; + } + + virtual QRectF indexedRect() const { + return m_sceneRect; + } + +protected : + void sceneRectChanged(const QRectF &rect) { + m_sceneRect = rect; + } + + virtual void clear() { + m_items.clear(); + } + + virtual void addItem(QGraphicsItem *item) { + m_items << item; + } + + virtual void removeItem(QGraphicsItem *item) { + m_items.removeAll(item); + } + +private: + QRectF m_sceneRect; + QList m_items; +}; + +#endif // QT_NO_GRAPHICSVIEW + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QGRAPHICSSCENELINEARINDEX_H diff --git a/src/gui/graphicsview/qgraphicsscenelinearindex_p.h b/src/gui/graphicsview/qgraphicsscenelinearindex_p.h deleted file mode 100644 index d21475c..0000000 --- a/src/gui/graphicsview/qgraphicsscenelinearindex_p.h +++ /dev/null @@ -1,118 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRAPHICSSCENELINEARINDEX_P_H -#define QGRAPHICSSCENELINEARINDEX_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include - -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -class Q_AUTOTEST_EXPORT QGraphicsSceneLinearIndex : public QGraphicsSceneIndex -{ - Q_OBJECT - -public: - QGraphicsSceneLinearIndex(QGraphicsScene *scene = 0): QGraphicsSceneIndex(scene) - { - } - - QList items(Qt::SortOrder order = Qt::AscendingOrder) const { - Q_UNUSED(order); - return m_items; - } - - virtual QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const { - Q_UNUSED(rect); - Q_UNUSED(order); - Q_UNUSED(deviceTransform); - return m_items; - } - - virtual QRectF indexedRect() const { - return m_sceneRect; - } - -protected : - void sceneRectChanged(const QRectF &rect) { - m_sceneRect = rect; - } - - virtual void clear() { - m_items.clear(); - } - - virtual void addItem(QGraphicsItem *item) { - m_items << item; - } - - virtual void removeItem(QGraphicsItem *item) { - m_items.removeAll(item); - } - -private: - QRectF m_sceneRect; - QList m_items; -}; - -QT_END_NAMESPACE - -#endif // QT_NO_GRAPHICSVIEW - -#endif // QGRAPHICSSCENELINEARINDEX_P_H -- cgit v0.12 From 5d682567d1acb79b2fa55ae8f005c5dcdc9aacb7 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Wed, 17 Jun 2009 14:27:46 +0200 Subject: API / code review for QGraphicsSceneIndex (internal API). A few minor modifications only, marked some things as ### obsolete, removed the public get/set for the index (it's internal anyway). --- src/gui/graphicsview/qgraphicsitem.h | 48 ++++++------ src/gui/graphicsview/qgraphicsscene.cpp | 90 ++++------------------ src/gui/graphicsview/qgraphicsscene.h | 11 +-- src/gui/graphicsview/qgraphicsscene_p.h | 40 ---------- .../graphicsview/qgraphicsscenebsptreeindex.cpp | 6 +- .../graphicsview/qgraphicsscenebsptreeindex_p.h | 40 ++++++++++ 6 files changed, 86 insertions(+), 149 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index ec16d26..12dcad2 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -141,7 +141,7 @@ public: QGraphicsItem(QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); @@ -208,8 +208,8 @@ public: Qt::MouseButtons acceptedMouseButtons() const; void setAcceptedMouseButtons(Qt::MouseButtons buttons); - bool acceptsHoverEvents() const; // obsolete - void setAcceptsHoverEvents(bool enabled); // obsolete + bool acceptsHoverEvents() const; // ### obsolete + void setAcceptsHoverEvents(bool enabled); // ### obsolete bool acceptHoverEvents() const; void setAcceptHoverEvents(bool enabled); @@ -534,7 +534,7 @@ class Q_GUI_EXPORT QAbstractGraphicsShapeItem : public QGraphicsItem public: QAbstractGraphicsShapeItem(QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); @@ -564,13 +564,13 @@ class Q_GUI_EXPORT QGraphicsPathItem : public QAbstractGraphicsShapeItem public: QGraphicsPathItem(QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); QGraphicsPathItem(const QPainterPath &path, QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); @@ -607,19 +607,19 @@ class Q_GUI_EXPORT QGraphicsRectItem : public QAbstractGraphicsShapeItem public: QGraphicsRectItem(QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); QGraphicsRectItem(const QRectF &rect, QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); QGraphicsRectItem(qreal x, qreal y, qreal w, qreal h, QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); @@ -660,19 +660,19 @@ class Q_GUI_EXPORT QGraphicsEllipseItem : public QAbstractGraphicsShapeItem public: QGraphicsEllipseItem(QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); QGraphicsEllipseItem(const QRectF &rect, QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); QGraphicsEllipseItem(qreal x, qreal y, qreal w, qreal h, QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); @@ -719,14 +719,14 @@ class Q_GUI_EXPORT QGraphicsPolygonItem : public QAbstractGraphicsShapeItem public: QGraphicsPolygonItem(QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); QGraphicsPolygonItem(const QPolygonF &polygon, QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); @@ -766,19 +766,19 @@ class Q_GUI_EXPORT QGraphicsLineItem : public QGraphicsItem public: QGraphicsLineItem(QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); QGraphicsLineItem(const QLineF &line, QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); QGraphicsLineItem(qreal x1, qreal y1, qreal x2, qreal y2, QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); @@ -826,13 +826,13 @@ public: QGraphicsPixmapItem(QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); QGraphicsPixmapItem(const QPixmap &pixmap, QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); @@ -888,13 +888,13 @@ class Q_GUI_EXPORT QGraphicsTextItem : public QGraphicsObject public: QGraphicsTextItem(QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); QGraphicsTextItem(const QString &text, QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); @@ -989,13 +989,13 @@ class Q_GUI_EXPORT QGraphicsSimpleTextItem : public QAbstractGraphicsShapeItem public: QGraphicsSimpleTextItem(QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); QGraphicsSimpleTextItem(const QString &text, QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); @@ -1035,7 +1035,7 @@ class Q_GUI_EXPORT QGraphicsItemGroup : public QGraphicsItem public: QGraphicsItemGroup(QGraphicsItem *parent = 0 #ifndef Q_QDOC - // obsolete argument + // ### obsolete argument , QGraphicsScene *scene = 0 #endif ); diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index a33cb3e..dacfc87 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -201,8 +201,6 @@ however, is done in constant time. This approach is ideal for dynamic scenes, where many items are added, moved or removed continuously. - \omitvalue CustomIndex - \sa setItemIndexMethod(), bspTreeDepth */ @@ -1529,85 +1527,19 @@ QGraphicsScene::ItemIndexMethod QGraphicsScene::itemIndexMethod() const Q_D(const QGraphicsScene); return d->indexMethod; } - -// Possibilities -// NoIndex -> CustomIndex : warning -// BspTreeIndex -> CustomIndex : warning -// CustomIndex -> CustomIndex : warning -// NoIndex -> BspTreeIndex : create an empty BSP if necessary -// BspTreeIndex -> BspTreeIndex : nothing -// CustomIndex -> BspTreeIndex : create BSP and transfer items -// NoIndex -> NoIndex : nothing -// BspTreeIndex -> NoIndex : nothing -// CustomIndex -> NoIndex : create BSP tree but do not populate void QGraphicsScene::setItemIndexMethod(ItemIndexMethod method) { Q_D(QGraphicsScene); - if (method == CustomIndex) { - qWarning("QGraphicsScene: Invalid index type %d", CustomIndex); + if (d->indexMethod == method) return; - } - if (d->indexMethod == method) { - return; - } - if (d->indexMethod == NoIndex && method == BspTreeIndex) { - QGraphicsSceneBspTreeIndex *tree = qobject_cast(d->index); - if (!tree) { - delete d->index; - d->index = new QGraphicsSceneBspTreeIndex(this); - } - } + d->indexMethod = method; - if (d->indexMethod == CustomIndex && method == BspTreeIndex) { - //We re-add in the new index all items from the old index - QGraphicsSceneIndex *oldIndex = d->index; + delete d->index; + if (method == BspTreeIndex) d->index = new QGraphicsSceneBspTreeIndex(this); - for (int i = 0 ; i < oldIndex->items().size() ; ++ i) - d->index->addItem(oldIndex->items().at(i)); - } - - if (d->indexMethod == CustomIndex && method == NoIndex) { + else d->index = new QGraphicsSceneLinearIndex(this); - } - - d->indexMethod = method; -} - -/*! - \internal - - \brief the item indexing method. - This method allow to apply an indexing algorithm \a index to the scene, to speed up - item discovery functions like items() and itemAt(). - - \sa sceneIndex(), QGraphicsSceneIndex -*/ -void QGraphicsScene::setSceneIndex(QGraphicsSceneIndex *index) -{ - Q_D(QGraphicsScene); - if (!index) { - qWarning("QGraphicsScene::setSceneIndex: Attempt to insert a null indexer"); - } else { - if (d->indexMethod == BspTreeIndex) { - delete d->index; - } - d->indexMethod = CustomIndex; - d->index = index; - } -} - -/*! - \internal - - This method return the current indexing algorithm of the scene. - - \sa setSceneIndex(), QGraphicsSceneIndex -*/ -QGraphicsSceneIndex* QGraphicsScene::sceneIndex() const -{ - Q_D(const QGraphicsScene); - return d->index; } /*! @@ -1814,7 +1746,8 @@ QList QGraphicsScene::items(const QPainterPath &path, Qt::ItemS \sa itemAt() */ -QList QGraphicsScene::items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const +QList QGraphicsScene::items(const QPointF &pos, Qt::ItemSelectionMode mode, + Qt::SortOrder order, const QTransform &deviceTransform) const { Q_D(const QGraphicsScene); return d->index->items(pos, mode, order, deviceTransform); @@ -1833,7 +1766,8 @@ QList QGraphicsScene::items(const QPointF &pos, Qt::ItemSelecti \sa itemAt() */ -QList QGraphicsScene::items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const +QList QGraphicsScene::items(const QRectF &rect, Qt::ItemSelectionMode mode, + Qt::SortOrder order, const QTransform &deviceTransform) const { Q_D(const QGraphicsScene); return d->index->items(rect, mode, order, deviceTransform); @@ -1852,7 +1786,8 @@ QList QGraphicsScene::items(const QRectF &rect, Qt::ItemSelecti \sa itemAt() */ -QList QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const +QList QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, + Qt::SortOrder order, const QTransform &deviceTransform) const { Q_D(const QGraphicsScene); return d->index->items(polygon, mode, order, deviceTransform); @@ -1871,7 +1806,8 @@ QList QGraphicsScene::items(const QPolygonF &polygon, Qt::ItemS \sa itemAt() */ -QList QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const +QList QGraphicsScene::items(const QPainterPath &path, Qt::ItemSelectionMode mode, + Qt::SortOrder order, const QTransform &deviceTransform) const { Q_D(const QGraphicsScene); return d->index->items(path, mode, order, deviceTransform); diff --git a/src/gui/graphicsview/qgraphicsscene.h b/src/gui/graphicsview/qgraphicsscene.h index 36374c8..b922be5 100644 --- a/src/gui/graphicsview/qgraphicsscene.h +++ b/src/gui/graphicsview/qgraphicsscene.h @@ -114,7 +114,6 @@ class Q_GUI_EXPORT QGraphicsScene : public QObject public: enum ItemIndexMethod { BspTreeIndex, - CustomIndex, NoIndex = -1 }; @@ -144,8 +143,6 @@ public: ItemIndexMethod itemIndexMethod() const; void setItemIndexMethod(ItemIndexMethod method); - void setSceneIndex(QGraphicsSceneIndex *index); - QGraphicsSceneIndex* sceneIndex() const; bool isSortCacheEnabled() const; void setSortCacheEnabled(bool enabled); @@ -162,10 +159,10 @@ public: QList items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; QList items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; - QList items(const QPointF &pos) const; - QList items(const QRectF &rect, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; - QList items(const QPolygonF &polygon, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; - QList items(const QPainterPath &path, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; + QList items(const QPointF &pos) const; // ### obsolete + QList items(const QRectF &rect, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; // ### obsolete + QList items(const QPolygonF &polygon, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; // ### obsolete + QList items(const QPainterPath &path, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; // ### obsolete QList collidingItems(const QGraphicsItem *item, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; QGraphicsItem *itemAt(const QPointF &pos) const; diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 563e016..8e05c00 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -229,46 +229,6 @@ public: QStyleOptionGraphicsItem styleOptionTmp; }; -static inline bool QRectF_intersects(const QRectF &s, const QRectF &r) -{ - qreal xp = s.left(); - qreal yp = s.top(); - qreal w = s.width(); - qreal h = s.height(); - qreal l1 = xp; - qreal r1 = xp; - if (w < 0) - l1 += w; - else - r1 += w; - - qreal l2 = r.left(); - qreal r2 = r.left(); - if (w < 0) - l2 += r.width(); - else - r2 += r.width(); - - if (l1 >= r2 || l2 >= r1) - return false; - - qreal t1 = yp; - qreal b1 = yp; - if (h < 0) - t1 += h; - else - b1 += h; - - qreal t2 = r.top(); - qreal b2 = r.top(); - if (r.height() < 0) - t2 += r.height(); - else - b2 += r.height(); - - return !(t1 >= b2 || t2 >= b1); -} - // QRectF::intersects() returns false always if either the source or target // rectangle's width or height are 0. This works around that problem. static inline void _q_adjustRect(QRectF *rect) diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp index 76fd218..969d3c5 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -589,12 +589,16 @@ void QGraphicsSceneBspTreeIndex::prepareBoundingRectChange(const QGraphicsItem * \a deviceTransform is the transformation apply to the view. */ -QList QGraphicsSceneBspTreeIndex::estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const +QList QGraphicsSceneBspTreeIndex::estimateItems(const QRectF &rect, Qt::SortOrder order, + const QTransform &deviceTransform) const { Q_D(const QGraphicsSceneBspTreeIndex); const_cast(d)->purgeRemovedItems(); const_cast(d)->_q_updateSortCache(); + // ### Handle items that ignore transformations + Q_UNUSED(deviceTransform); + QList rectItems = d->bsp.items(rect); // Fill in with any unindexed items for (int i = 0; i < d->unindexedItems.size(); ++i) { diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h index 6bafbc8..b6f782d 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h @@ -142,6 +142,46 @@ static inline bool qt_notclosestLeaf(const QGraphicsItem *item1, const QGraphics } +static inline bool QRectF_intersects(const QRectF &s, const QRectF &r) +{ + qreal xp = s.left(); + qreal yp = s.top(); + qreal w = s.width(); + qreal h = s.height(); + qreal l1 = xp; + qreal r1 = xp; + if (w < 0) + l1 += w; + else + r1 += w; + + qreal l2 = r.left(); + qreal r2 = r.left(); + if (w < 0) + l2 += r.width(); + else + r2 += r.width(); + + if (l1 >= r2 || l2 >= r1) + return false; + + qreal t1 = yp; + qreal b1 = yp; + if (h < 0) + t1 += h; + else + b1 += h; + + qreal t2 = r.top(); + qreal b2 = r.top(); + if (r.height() < 0) + t2 += r.height(); + else + b2 += r.height(); + + return !(t1 >= b2 || t2 >= b1); +} + QT_END_NAMESPACE #endif // QGRAPHICSSCENEBSPTREEINDEX_P_H -- cgit v0.12 From 625dadcc9b88dccebf607b84089ab960740b94f2 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Wed, 17 Jun 2009 14:36:55 +0200 Subject: Don't lose all the items when we switch item index method. Readd the items to the new index. Reviewed-by: Alexis --- src/gui/graphicsview/qgraphicsscene.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index dacfc87..36af30d 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -1535,11 +1535,14 @@ void QGraphicsScene::setItemIndexMethod(ItemIndexMethod method) d->indexMethod = method; + QList oldItems = d->index->items(); delete d->index; if (method == BspTreeIndex) d->index = new QGraphicsSceneBspTreeIndex(this); else d->index = new QGraphicsSceneLinearIndex(this); + for (int i = 0; i < oldItems.size(); ++i) + d->index->addItem(oldItems.at(i)); } /*! -- cgit v0.12 From ac8bf5ec1f99d0e00e3ffefe53306c0d511376bf Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Wed, 17 Jun 2009 14:46:54 +0200 Subject: More cleanups during code review. Reviewed-by: Alexis --- src/gui/graphicsview/qgraphicsscene.cpp | 104 --------------------------- src/gui/graphicsview/qgraphicsscene_p.h | 4 -- src/gui/graphicsview/qgraphicssceneindex.cpp | 54 +++++++++----- src/gui/graphicsview/qgraphicssceneindex.h | 18 +++-- 4 files changed, 47 insertions(+), 133 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 36af30d..380ac20 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -1097,110 +1097,6 @@ QGraphicsWidget *QGraphicsScenePrivate::windowForItem(const QGraphicsItem *item) return 0; } -void QGraphicsScenePrivate::recursive_items_helper(QGraphicsItem *item, QRectF rect, - QList *items, - const QTransform &parentTransform, - const QTransform &viewTransform, - Qt::ItemSelectionMode mode, Qt::SortOrder order, - qreal parentOpacity) const -{ - // Calculate opacity. - qreal opacity; - if (item) { - if (!item->d_ptr->visible) - return; - QGraphicsItem *p = item->d_ptr->parent; - bool itemIgnoresParentOpacity = item->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity; - bool parentDoesntPropagateOpacity = (p && (p->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)); - if (!itemIgnoresParentOpacity && !parentDoesntPropagateOpacity) { - opacity = parentOpacity * item->opacity(); - } else { - opacity = item->d_ptr->opacity; - } - if (opacity == 0.0 && !(item->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) - return; - } else { - opacity = parentOpacity; - } - - // Calculate the full transform for this item. - QTransform transform = parentTransform; - bool keep = false; - if (item) { - item->d_ptr->combineTransformFromParent(&transform, &viewTransform); - - // ### This does not take the clip into account. - QRectF brect = item->boundingRect(); - _q_adjustRect(&brect); - - keep = true; - if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect) - keep = rect.contains(transform.mapRect(brect)) && rect != brect; - else - keep = rect.intersects(transform.mapRect(brect)); - - if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { - QPainterPath rectPath; - rectPath.addRect(rect); - keep = itemCollidesWithPath(item, transform.inverted().map(rectPath), mode); - } - } - - bool childClip = (item && (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)); - bool dontProcessItem = !item || !keep; - bool dontProcessChildren = item && dontProcessItem && childClip; - - // Find and sort children. - QList &children = item ? item->d_ptr->children : const_cast(this)->topLevelItems; - if (!dontProcessChildren) { - if (item && item->d_ptr->needSortChildren) { - item->d_ptr->needSortChildren = 0; - qStableSort(children.begin(), children.end(), qt_notclosestLeaf); - } else if (!item && needSortTopLevelItems) { - const_cast(this)->needSortTopLevelItems = false; - qStableSort(children.begin(), children.end(), qt_notclosestLeaf); - } - } - - childClip &= !dontProcessChildren & !children.isEmpty(); - - // Clip. - if (childClip) - rect &= transform.map(item->shape()).controlPointRect(); - - // Process children behind - int i = 0; - if (!dontProcessChildren) { - for (i = 0; i < children.size(); ++i) { - QGraphicsItem *child = children.at(i); - if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent)) - break; - recursive_items_helper(child, rect, items, transform, viewTransform, - mode, order, opacity); - } - } - - // Process item - if (!dontProcessItem) - items->append(item); - - // Process children in front - if (!dontProcessChildren) { - for (; i < children.size(); ++i) - recursive_items_helper(children.at(i), rect, items, transform, viewTransform, - mode, order, opacity); - } - - if (!item && order == Qt::AscendingOrder) { - int n = items->size(); - for (int i = 0; i < n / 2; ++i) { - QGraphicsItem *tmp = (*items)[n - i - 1]; - (*items)[n - i - 1] = (*items)[i]; - (*items)[i] = tmp; - } - } -} - /*! \internal diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 8e05c00..538ff3f 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -188,10 +188,6 @@ public: void mousePressEventHandler(QGraphicsSceneMouseEvent *mouseEvent); QGraphicsWidget *windowForItem(const QGraphicsItem *item) const; - void recursive_items_helper(QGraphicsItem *item, QRectF rect, QList *items, - const QTransform &parentTransform, const QTransform &viewTransform, - Qt::ItemSelectionMode mode, Qt::SortOrder order, qreal parentOpacity = 1.0) const; - void drawItemHelper(QGraphicsItem *item, QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget, bool painterStateProtection); diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index 966d8fe..4ca1c02 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -119,9 +119,8 @@ public: else keep = rect.intersects(transform.mapRect(brect)); - if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { + if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) keep = QGraphicsScenePrivate::get(scene)->itemCollidesWithPath(item, transform.inverted().map(path), mode); - } return keep; } QPainterPath path; @@ -290,24 +289,27 @@ QRectF QGraphicsSceneIndex::indexedRect() const } /*! - \fn QList QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const + \fn QList QGraphicsSceneIndex::items(const QPointF &pos, + Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform + &deviceTransform) const - Returns all visible items that, depending on \a mode, are at the specified \a pos - and return a list sorted using \a order. + Returns all visible items that, depending on \a mode, are at the specified + \a pos and return a list sorted using \a order. The default value for \a mode is Qt::IntersectsItemShape; all items whose exact shape intersects with \a pos are returned. \a deviceTransform is the transformation apply to the view. - This method use the estimation of the index (estimateItems) and refine - the list to get an exact result. If you want to implement your own - refinement algorithm you can reimplement this method. + This method use the estimation of the index (estimateItems) and refine the + list to get an exact result. If you want to implement your own refinement + algorithm you can reimplement this method. \sa estimateItems() */ -QList QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const +QList QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSelectionMode mode, + Qt::SortOrder order, const QTransform &deviceTransform) const { Q_D(const QGraphicsSceneIndex); QList itemList; @@ -319,7 +321,9 @@ QList QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSe } /*! - \fn QList QGraphicsSceneIndex::items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const + \fn QList QGraphicsSceneIndex::items(const QRectF &rect, + Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform + &deviceTransform) const \overload @@ -338,7 +342,8 @@ QList QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSe \sa estimateItems() */ -QList QGraphicsSceneIndex::items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const +QList QGraphicsSceneIndex::items(const QRectF &rect, Qt::ItemSelectionMode mode, + Qt::SortOrder order, const QTransform &deviceTransform) const { Q_D(const QGraphicsSceneIndex); QList itemList; @@ -349,7 +354,9 @@ QList QGraphicsSceneIndex::items(const QRectF &rect, Qt::ItemSe } /*! - \fn QList QGraphicsSceneIndex::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const + \fn QList QGraphicsSceneIndex::items(const QPolygonF + &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const + QTransform &deviceTransform) const \overload @@ -368,7 +375,8 @@ QList QGraphicsSceneIndex::items(const QRectF &rect, Qt::ItemSe \sa estimateItems() */ -QList QGraphicsSceneIndex::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const +QList QGraphicsSceneIndex::items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, + Qt::SortOrder order, const QTransform &deviceTransform) const { Q_D(const QGraphicsSceneIndex); QList itemList; @@ -384,7 +392,9 @@ QList QGraphicsSceneIndex::items(const QPolygonF &polygon, Qt:: } /*! - \fn QList QGraphicsSceneIndex::items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const + \fn QList QGraphicsSceneIndex::items(const QPainterPath + &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform + &deviceTransform) const \overload @@ -403,7 +413,8 @@ QList QGraphicsSceneIndex::items(const QPolygonF &polygon, Qt:: \sa estimateItems() */ -QList QGraphicsSceneIndex::items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const +QList QGraphicsSceneIndex::items(const QPainterPath &path, Qt::ItemSelectionMode mode, + Qt::SortOrder order, const QTransform &deviceTransform) const { Q_D(const QGraphicsSceneIndex); QList itemList; @@ -421,13 +432,16 @@ QList QGraphicsSceneIndex::items(const QPainterPath &path, Qt:: This method return a list sorted using \a order. \a deviceTransform is the transformation apply to the view. */ -QList QGraphicsSceneIndex::estimateItems(const QPointF &point, Qt::SortOrder order, const QTransform &deviceTransform) const +QList QGraphicsSceneIndex::estimateItems(const QPointF &point, Qt::SortOrder order, + const QTransform &deviceTransform) const { return estimateItems(QRectF(point, QSize(1,1)), order, deviceTransform); } /*! - \fn virtual QList QGraphicsSceneIndex::estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const = 0 + \fn virtual QList + QGraphicsSceneIndex::estimateItems(const QRectF &rect, Qt::SortOrder + order, const QTransform &deviceTransform) const = 0 This pure virtual function return an estimation of items in the \a rect. This method return a list sorted using \a order. @@ -436,8 +450,10 @@ QList QGraphicsSceneIndex::estimateItems(const QPointF &point, */ /*! - \fn virtual QList QGraphicsSceneIndex::items(Qt::SortOrder order = Qt::AscendingOrder) const = 0; - This pure virtual function all items in the index and sort them using \a order. + \fn virtual QList + QGraphicsSceneIndex::items(Qt::SortOrder order = Qt::AscendingOrder) const + = 0; This pure virtual function all items in the index and sort them using + \a order. */ /*! diff --git a/src/gui/graphicsview/qgraphicssceneindex.h b/src/gui/graphicsview/qgraphicssceneindex.h index c0e415c..ddce9d4 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.h +++ b/src/gui/graphicsview/qgraphicssceneindex.h @@ -85,12 +85,18 @@ public: virtual QRectF indexedRect() const; virtual QList items(Qt::SortOrder order = Qt::AscendingOrder) const = 0; - virtual QList items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; - virtual QList items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; - virtual QList items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; - virtual QList items(const QPainterPath &path, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; - virtual QList estimateItems(const QPointF &point, Qt::SortOrder order, const QTransform &deviceTransform) const; - virtual QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const = 0; + virtual QList items(const QPointF &pos, Qt::ItemSelectionMode mode, + Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; + virtual QList items(const QRectF &rect, Qt::ItemSelectionMode mode, + Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; + virtual QList items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, + Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; + virtual QList items(const QPainterPath &path, Qt::ItemSelectionMode mode, + Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; + virtual QList estimateItems(const QPointF &point, + Qt::SortOrder order, const QTransform &deviceTransform) const; + virtual QList estimateItems(const QRectF &rect, + Qt::SortOrder order, const QTransform &deviceTransform) const = 0; protected: virtual void clear(); -- cgit v0.12 From 0d839e3655d985920aff81882bd444605d97c21c Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Thu, 18 Jun 2009 14:28:29 +0200 Subject: Changes after first round of code reviewing. This change removes all code that handles ItemIgnoresTransformations from QGraphicsView, and changes the APIs of the scene index intersectors. Reviewed-by: Alexis --- src/gui/graphicsview/qgraphicsitem.cpp | 33 ++-- src/gui/graphicsview/qgraphicsitem_p.h | 9 + src/gui/graphicsview/qgraphicsscene.cpp | 141 ++++++-------- src/gui/graphicsview/qgraphicsscene.h | 17 +- src/gui/graphicsview/qgraphicsscene_p.h | 4 +- .../graphicsview/qgraphicsscenebsptreeindex.cpp | 96 +++++---- src/gui/graphicsview/qgraphicsscenebsptreeindex.h | 2 +- .../graphicsview/qgraphicsscenebsptreeindex_p.h | 5 +- src/gui/graphicsview/qgraphicssceneindex.cpp | 216 ++++++++++++++------- src/gui/graphicsview/qgraphicssceneindex.h | 2 +- src/gui/graphicsview/qgraphicssceneindex_p.h | 19 +- src/gui/graphicsview/qgraphicsview.cpp | 161 ++++----------- src/gui/graphicsview/qgraphicsview_p.h | 7 +- 13 files changed, 368 insertions(+), 344 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 593d7be..75683d8 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -857,6 +857,11 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent) if (newParent == parent) return; + if (scene) { + // Deliver the change to the index + scene->d_func()->index->itemChange(q, QGraphicsItem::ItemParentChange, newParentVariant); + } + if (QGraphicsWidget *w = isWidget ? static_cast(q) : q->parentWidget()) { // Update the child focus chain; when reparenting a widget that has a // focus child, ensure that that focus child clears its focus child @@ -951,11 +956,6 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent) // Deliver post-change notification q->itemChange(QGraphicsItem::ItemParentHasChanged, newParentVariant); - if (scene) { - // Deliver the change to the index - scene->d_func()->index->itemChanged(q, QGraphicsItem::ItemParentHasChanged, newParentVariant); - } - if (isObject) emit static_cast(q)->parentChanged(); } @@ -1426,6 +1426,8 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags) flags = GraphicsItemFlags(itemChange(ItemFlagsChange, quint32(flags)).toUInt()); if (quint32(d_ptr->flags) == quint32(flags)) return; + if (d_ptr->scene) + d_ptr->scene->d_func()->index->itemChange(this, ItemFlagsChange, quint32(flags)); // Flags that alter the geometry of the item (or its children). const quint32 geomChangeFlagsMask = (ItemClipsChildrenToShape | ItemClipsToShape | ItemIgnoresTransformations); @@ -3577,17 +3579,20 @@ void QGraphicsItem::setZValue(qreal z) qreal newZ = qreal(newZVariant.toDouble()); if (newZ == d_ptr->z) return; + + if (d_ptr->scene) { + // Z Value has changed, we have to notify the index. + d_ptr->scene->d_func()->index->itemChange(this, ItemZValueChange, newZVariant); + } + d_ptr->z = newZ; if (d_ptr->parent) d_ptr->parent->d_ptr->needSortChildren = 1; else if (d_ptr->scene) d_ptr->scene->d_func()->needSortTopLevelItems = 1; - if (d_ptr->scene) { + if (d_ptr->scene) d_ptr->scene->d_func()->markDirty(this, QRectF(), /*invalidateChildren=*/true); - //Z Value has changed, we have to notify the index. - d_ptr->scene->d_func()->index->itemChanged(this, ItemZValueChange, z); - } itemChange(ItemZValueHasChanged, newZVariant); @@ -9655,17 +9660,11 @@ QDebug operator<<(QDebug debug, QGraphicsItem *item) return debug; } - QStringList flags; - if (item->isVisible()) flags << QLatin1String("isVisible"); - if (item->isEnabled()) flags << QLatin1String("isEnabled"); - if (item->isSelected()) flags << QLatin1String("isSelected"); - if (item->hasFocus()) flags << QLatin1String("HasFocus"); - debug << "QGraphicsItem(this =" << ((void*)item) << ", parent =" << ((void*)item->parentItem()) << ", pos =" << item->pos() - << ", z =" << item->zValue() << ", flags = {" - << flags.join(QLatin1String("|")) << " })"; + << ", z =" << item->zValue() << ", flags = " + << item->flags() << ")"; return debug; } diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 9c1ee4f..1c95a62 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -158,6 +158,15 @@ public: inline virtual ~QGraphicsItemPrivate() { } + static const QGraphicsItemPrivate *get(const QGraphicsItem *item) + { + return item->d_ptr; + } + static QGraphicsItemPrivate *get(QGraphicsItem *item) + { + return item->d_ptr; + } + void updateAncestorFlag(QGraphicsItem::GraphicsItemFlag childFlag, AncestorFlag flag = NoFlag, bool enabled = false, bool root = true); void setIsMemberOfGroup(bool enabled); diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 380ac20..55f0f20 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -774,41 +774,8 @@ QList QGraphicsScenePrivate::itemsAtPosition(const QPoint &scre { Q_Q(const QGraphicsScene); QGraphicsView *view = widget ? qobject_cast(widget->parentWidget()) : 0; - QList items; - if (view) - items = view->items(view->viewport()->mapFromGlobal(screenPos)); - else - items = q->items(scenePos); - return items; -} - -/*! - \internal - - Checks if item collides with the path and mode, but also checks that if it - doesn't collide, maybe its frame rect will. -*/ -bool QGraphicsScenePrivate::itemCollidesWithPath(QGraphicsItem *item, - const QPainterPath &path, - Qt::ItemSelectionMode mode) -{ - if (item->collidesWithPath(path, mode)) - return true; - if (item->isWidget()) { - // Check if this is a window, and if its frame rect collides. - QGraphicsWidget *widget = static_cast(item); - if (widget->isWindow()) { - QRectF frameRect = widget->windowFrameRect(); - QPainterPath framePath; - framePath.addRect(frameRect); - bool intersects = path.intersects(frameRect); - if (mode == Qt::IntersectsItemShape || mode == Qt::IntersectsItemBoundingRect) - return intersects || path.contains(frameRect.topLeft()) - || framePath.contains(path.elementAt(0)); - return !intersects && path.contains(frameRect.topLeft()); - } - } - return false; + return q->items(scenePos, Qt::IntersectsItemShape, Qt::AscendingOrder, + view ? view->viewportTransform() : QTransform()); } /*! @@ -820,7 +787,7 @@ void QGraphicsScenePrivate::storeMouseButtonsForMouseGrabber(QGraphicsSceneMouse if (event->buttons() & i) { mouseGrabberButtonDownPos.insert(Qt::MouseButton(i), mouseGrabberItems.last()->d_ptr->genericMapFromScene(event->scenePos(), - event->widget())); + event->widget())); mouseGrabberButtonDownScenePos.insert(Qt::MouseButton(i), event->scenePos()); mouseGrabberButtonDownScreenPos.insert(Qt::MouseButton(i), event->screenPos()); } @@ -1282,6 +1249,8 @@ QGraphicsScene::~QGraphicsScene() QRectF QGraphicsScene::sceneRect() const { Q_D(const QGraphicsScene); + /// ### Remove? The growing items bounding rect might be managed + // by the scene. return d->index->indexedRect(); } void QGraphicsScene::setSceneRect(const QRectF &rect) @@ -1332,6 +1301,8 @@ void QGraphicsScene::setSceneRect(const QRectF &rect) void QGraphicsScene::render(QPainter *painter, const QRectF &target, const QRectF &source, Qt::AspectRatioMode aspectRatioMode) { + // ### Switch to using the recursive rendering algorithm instead. + // Default source rect = scene rect QRectF sourceRect = source; if (sourceRect.isNull()) @@ -1431,14 +1402,16 @@ void QGraphicsScene::setItemIndexMethod(ItemIndexMethod method) d->indexMethod = method; - QList oldItems = d->index->items(); + QList oldItems = d->index->items(Qt::AscendingOrder); delete d->index; if (method == BspTreeIndex) d->index = new QGraphicsSceneBspTreeIndex(this); else d->index = new QGraphicsSceneLinearIndex(this); - for (int i = 0; i < oldItems.size(); ++i) + for (int i = oldItems.size() - 1; i >= 0; --i) d->index->addItem(oldItems.at(i)); + + d->index->sceneRectChanged(d->sceneRect); } /*! @@ -1476,7 +1449,7 @@ void QGraphicsScene::setItemIndexMethod(ItemIndexMethod method) int QGraphicsScene::bspTreeDepth() const { Q_D(const QGraphicsScene); - QGraphicsSceneBspTreeIndex *bspTree = qobject_cast(d->index); + QGraphicsSceneBspTreeIndex *bspTree = qobject_cast(d->index); return bspTree ? bspTree->bspTreeDepth() : 0; } void QGraphicsScene::setBspTreeDepth(int depth) @@ -1487,14 +1460,11 @@ void QGraphicsScene::setBspTreeDepth(int depth) return; } - QGraphicsSceneBspTreeIndex *bspTree = qobject_cast(d->index); + QGraphicsSceneBspTreeIndex *bspTree = qobject_cast(d->index); if (!bspTree) { qWarning("QGraphicsScene::setBspTreeDepth: can not apply if indexing method is not BSP"); return; } - if (bspTree->bspTreeDepth() == depth) - return; - bspTree->setBspTreeDepth(depth); } @@ -1502,37 +1472,21 @@ void QGraphicsScene::setBspTreeDepth(int depth) \property QGraphicsScene::sortCacheEnabled \brief whether sort caching is enabled \since 4.5 + \obsolete - When enabled, this property adds a cache that speeds up sorting and - transformations for scenes with deep hierarchies (i.e., items with many - levels of descendents), at the cost of using more memory (approx. 100 more - bytes of memory per item). - - Items that are not part of a deep hierarchy suffer no penalty from this - cache. + Since Qt 4.6, this property has no effect. */ bool QGraphicsScene::isSortCacheEnabled() const { Q_D(const QGraphicsScene); - QGraphicsSceneBspTreeIndex *bspTree = qobject_cast(d->index); - if (!bspTree) { - qWarning("QGraphicsScene::isSortCacheEnabled: can not apply if indexing method is not BSP"); - return false; - } - return bspTree->d_func()->sortCacheEnabled; + return d->sortCacheEnabled; } void QGraphicsScene::setSortCacheEnabled(bool enabled) { Q_D(QGraphicsScene); - QGraphicsSceneBspTreeIndex *bspTree = qobject_cast(d->index); - if (!bspTree) { - qWarning("QGraphicsScene::isSortCacheEnabled: can not apply if indexing method is not BSP"); + if (d->sortCacheEnabled == enabled) return; - } - if (enabled == bspTree->d_func()->sortCacheEnabled) - return; - if ((bspTree->d_func()->sortCacheEnabled = enabled)) - bspTree->d_func()->invalidateSortCache(); + d->sortCacheEnabled = enabled; } /*! @@ -1544,6 +1498,7 @@ void QGraphicsScene::setSortCacheEnabled(bool enabled) */ QRectF QGraphicsScene::itemsBoundingRect() const { + // Does not take untransformable items into account. QRectF boundingRect; foreach (QGraphicsItem *item, items()) boundingRect |= item->sceneBoundingRect(); @@ -1558,7 +1513,19 @@ QRectF QGraphicsScene::itemsBoundingRect() const QList QGraphicsScene::items() const { Q_D(const QGraphicsScene); - return d->index->items(); + return d->index->items(Qt::AscendingOrder); +} + +/*! + Returns an ordered list of all items on the scene. \a order decides the + sorting. + + \sa addItem(), removeItem() +*/ +QList QGraphicsScene::items(Qt::SortOrder order) const +{ + Q_D(const QGraphicsScene); + return d->index->items(order); } /*! @@ -1732,6 +1699,7 @@ QList QGraphicsScene::collidingItems(const QGraphicsItem *item, return QList(); } + // Does not support ItemIgnoresTransformations. QList tmp; foreach (QGraphicsItem *itemInVicinity, d->index->estimateItems(item->sceneBoundingRect(), Qt::AscendingOrder, QTransform())) { if (item != itemInVicinity && item->collidesWithItem(itemInVicinity, mode)) @@ -1756,6 +1724,13 @@ QGraphicsItem *QGraphicsScene::itemAt(const QPointF &pos) const return itemsAtPoint.isEmpty() ? 0 : itemsAtPoint.first(); } +QGraphicsItem *QGraphicsScene::itemAt(const QPointF &pos, const QTransform &deviceTransform) const +{ + QList itemsAtPoint = items(pos, Qt::IntersectsItemShape, + Qt::AscendingOrder, deviceTransform); + return itemsAtPoint.isEmpty() ? 0 : itemsAtPoint.first(); +} + /*! \fn QGraphicsScene::itemAt(qreal x, qreal y) const \overload @@ -1831,6 +1806,21 @@ void QGraphicsScene::setSelectionArea(const QPainterPath &path) */ void QGraphicsScene::setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode mode) { + setSelectionArea(path, Qt::IntersectsItemShape, QTransform()); +} + +/*! + \overload + \since 4.3 + + Sets the selection area to \a path using \a mode to determine if items are + included in the selection area. + + \sa clearSelection(), selectionArea() +*/ +void QGraphicsScene::setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode mode, + const QTransform &deviceTransform) +{ Q_D(QGraphicsScene); // Note: with boolean path operations, we can improve performance here @@ -1846,7 +1836,7 @@ void QGraphicsScene::setSelectionArea(const QPainterPath &path, Qt::ItemSelectio bool changed = false; // Set all items in path to selected. - foreach (QGraphicsItem *item, items(path, mode)) { + foreach (QGraphicsItem *item, items(path, mode, Qt::AscendingOrder, deviceTransform)) { if (item->flags() & QGraphicsItem::ItemIsSelectable) { if (!item->isSelected()) changed = true; @@ -1904,7 +1894,10 @@ void QGraphicsScene::clear() { Q_D(QGraphicsScene); QList items = d->index->items(); +#if 1 QList toDelete; + // ### As the item list is already in ascending order, + // the items should be deleted in topological order. // Recursive descent delete for (int i = 0; i < items.size(); ++i) { if (QGraphicsItem *item = items.at(i)) { @@ -1912,11 +1905,13 @@ void QGraphicsScene::clear() toDelete << item; } } - //We delete all top level items + // We delete all top level items qDeleteAll(toDelete); +#else + qDeleteAll(items); +#endif d->lastItemCount = 0; d->index->clear(); - d->largestUntransformableItem = QRectF(); d->allItemsIgnoreHoverEvents = true; d->allItemsUseDefaultCursor = true; } @@ -4129,16 +4124,6 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * children = &this->topLevelItems; } else { QRectF sceneRect = viewTransform.inverted().mapRect(QRectF(exposedRegion->boundingRect().adjusted(-1, -1, 1, 1))); - if (!largestUntransformableItem.isEmpty()) { - // ### Nuke this when we move the indexing code into a separate - // class. All the largestUntransformableItem code should then go - // away, and the estimate function should return untransformable - // items as well. - QRectF untr = largestUntransformableItem; - QRectF ltri = viewTransform.inverted().mapRect(untr); - ltri.adjust(-untr.width(), -untr.height(), untr.width(), untr.height()); - sceneRect.adjust(-ltri.width(), -ltri.height(), ltri.width(), ltri.height()); - } tmp = index->estimateItems(sceneRect, Qt::DescendingOrder, viewTransform); QList tli; diff --git a/src/gui/graphicsview/qgraphicsscene.h b/src/gui/graphicsview/qgraphicsscene.h index b922be5..421adbd 100644 --- a/src/gui/graphicsview/qgraphicsscene.h +++ b/src/gui/graphicsview/qgraphicsscene.h @@ -153,6 +153,7 @@ public: QRectF itemsBoundingRect() const; QList items() const; + QList items(Qt::SortOrder order) const; // ### Qt 5: unify QList items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; QList items(const QRectF &rect, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; @@ -165,17 +166,25 @@ public: QList items(const QPainterPath &path, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; // ### obsolete QList collidingItems(const QGraphicsItem *item, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const; - QGraphicsItem *itemAt(const QPointF &pos) const; + + QGraphicsItem *itemAt(const QPointF &pos) const; // ### obsolete + QGraphicsItem *itemAt(const QPointF &pos, const QTransform &deviceTransform) const; inline QList items(qreal x, qreal y, qreal w, qreal h, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape) const - { return items(QRectF(x, y, w, h), mode); } - inline QGraphicsItem *itemAt(qreal x, qreal y) const + { return items(QRectF(x, y, w, h), mode); } // ### obsolete + inline QList items(qreal x, qreal y, qreal w, qreal h, Qt::ItemSelectionMode mode, Qt::SortOrder order, + const QTransform &deviceTransform = QTransform()) const + { return items(QRectF(x, y, w, h), mode, order, deviceTransform); } + inline QGraphicsItem *itemAt(qreal x, qreal y) const // ### obsolete { return itemAt(QPointF(x, y)); } + inline QGraphicsItem *itemAt(qreal x, qreal y, const QTransform &deviceTransform) const + { return itemAt(QPointF(x, y), deviceTransform); } QList selectedItems() const; QPainterPath selectionArea() const; void setSelectionArea(const QPainterPath &path); - void setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode); + void setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode mode); + void setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode mode, const QTransform &deviceTransform); QGraphicsItemGroup *createItemGroup(const QList &items); void destroyItemGroup(QGraphicsItemGroup *group); diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 538ff3f..a081e04 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -96,7 +96,6 @@ public: QRectF sceneRect; bool hasSceneRect; QRectF growingItemsBoundingRect; - QRectF largestUntransformableItem; void _q_emitUpdated(); QList updatedRects; @@ -162,7 +161,6 @@ public: QList itemsAtPosition(const QPoint &screenPos, const QPointF &scenePos, QWidget *widget) const; - static bool itemCollidesWithPath(QGraphicsItem *item, const QPainterPath &path, Qt::ItemSelectionMode mode); void storeMouseButtonsForMouseGrabber(QGraphicsSceneMouseEvent *event); QList views; @@ -188,6 +186,8 @@ public: void mousePressEventHandler(QGraphicsSceneMouseEvent *mouseEvent); QGraphicsWidget *windowForItem(const QGraphicsItem *item) const; + bool sortCacheEnabled; // for compatibility + void drawItemHelper(QGraphicsItem *item, QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget, bool painterStateProtection); diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp index 969d3c5..40cafa6 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -170,11 +170,6 @@ void QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex() unindexedItems = indexedItems; lastItemCount = indexedItems.size(); q->scene()->update(); - - // Take this opportunity to reset our largest-item counter for - // untransformable items. When the items are inserted into the BSP - // tree, we'll get an accurate calculation. - scenePrivate->largestUntransformableItem = QRectF(); } // Insert all unindexed items into the tree. @@ -185,19 +180,6 @@ void QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex() continue; bsp.insertItem(item, rect); - - // If the item ignores view transformations, update our - // largest-item-counter to ensure that the view can accurately - // discover untransformable items when drawing. - if (item->d_ptr->itemIsUntransformable()) { - QGraphicsItem *topmostUntransformable = item; - while (topmostUntransformable && (topmostUntransformable->d_ptr->ancestorFlags - & QGraphicsItemPrivate::AncestorIgnoresTransformations)) { - topmostUntransformable = topmostUntransformable->parentItem(); - } - // ### Verify that this is the correct largest untransformable rectangle. - scenePrivate->largestUntransformableItem |= item->mapToItem(topmostUntransformable, item->boundingRect()).boundingRect(); - } } } unindexedItems.clear(); @@ -467,17 +449,23 @@ void QGraphicsSceneBspTreeIndex::addItem(QGraphicsItem *item) // Indexing requires sceneBoundingRect(), but because \a item might // not be completely constructed at this point, we need to store it in // a temporary list and schedule an indexing for later. - d->unindexedItems << item; - item->d_func()->index = -1; - d->startIndexTimer(0); + item->d_ptr->index = -1; + if (item->d_ptr->itemIsUntransformable()) { + d->untransformableItems << item; + } else { + d->unindexedItems << item; + d->startIndexTimer(0); + } } /*! This really add the item in the BSP. \internal */ -void QGraphicsSceneBspTreeIndexPrivate::addToIndex(QGraphicsItem *item) +void QGraphicsSceneBspTreeIndexPrivate::addToBspTree(QGraphicsItem *item) { + if (item->d_ptr->itemIsUntransformable()) + return; if (item->d_func()->index != -1) { bsp.insertItem(item, item->sceneBoundingRect()); foreach (QGraphicsItem *child, item->children()) @@ -496,10 +484,11 @@ void QGraphicsSceneBspTreeIndexPrivate::addToIndex(QGraphicsItem *item) void QGraphicsSceneBspTreeIndex::removeItem(QGraphicsItem *item) { Q_D(QGraphicsSceneBspTreeIndex); + // Note: This will access item's sceneBoundingRect(), which (as this is // C++) is why we cannot call removeItem() from QGraphicsItem's // destructor. - d->removeFromIndex(item); + d->removeFromBspTree(item); // Invalidate any sort caching; arrival of a new item means we need to // resort. @@ -511,7 +500,10 @@ void QGraphicsSceneBspTreeIndex::removeItem(QGraphicsItem *item) d->freeItemIndexes << index; d->indexedItems[index] = 0; } else { - d->unindexedItems.removeAll(item); + if (item->d_ptr->itemIsUntransformable()) + d->untransformableItems.removeOne(item); + else + d->unindexedItems.removeOne(item); } } @@ -539,7 +531,10 @@ void QGraphicsSceneBspTreeIndex::deleteItem(QGraphicsItem *item) } else { // Recently added items are purged immediately. unindexedItems() never // contains stale items. - d->unindexedItems.removeAll(item); + if (item->d_ptr->itemIsUntransformable()) + d->untransformableItems.removeOne(item); + else + d->unindexedItems.removeOne(item); scene()->update(); } } @@ -548,8 +543,11 @@ void QGraphicsSceneBspTreeIndex::deleteItem(QGraphicsItem *item) Really remove the item from the BSP \internal */ -void QGraphicsSceneBspTreeIndexPrivate::removeFromIndex(QGraphicsItem *item) +void QGraphicsSceneBspTreeIndexPrivate::removeFromBspTree(QGraphicsItem *item) { + if (item->d_ptr->itemIsUntransformable()) + return; + if (item->d_func()->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) { // ### remove from child index only if applicable return; @@ -579,7 +577,7 @@ void QGraphicsSceneBspTreeIndex::prepareBoundingRectChange(const QGraphicsItem * // Note: This will access item's sceneBoundingRect(), which (as this is // C++) is why we cannot call removeItem() from QGraphicsItem's // destructor. - d->removeFromIndex(const_cast(item)); + d->removeFromBspTree(const_cast(item)); } /*! @@ -633,7 +631,8 @@ QList QGraphicsSceneBspTreeIndex::items(Qt::SortOrder order) co Q_D(const QGraphicsSceneBspTreeIndex); const_cast(d)->purgeRemovedItems(); QList itemList; - // If freeItemIndexes is empty, we know there are no holes in indexedItems and + + // If freeItemIndexes is empty, we know there are no holes in indexedItems and // unindexedItems. if (d->freeItemIndexes.isEmpty()) { if (d->unindexedItems.isEmpty()) { @@ -649,6 +648,7 @@ QList QGraphicsSceneBspTreeIndex::items(Qt::SortOrder order) co itemList << item; } } + itemList += d->untransformableItems; if (order != -1) { //We sort descending order d->sortItems(&itemList, order, d->sortCacheEnabled); @@ -692,6 +692,8 @@ int QGraphicsSceneBspTreeIndex::bspTreeDepth() void QGraphicsSceneBspTreeIndex::setBspTreeDepth(int depth) { Q_D(QGraphicsSceneBspTreeIndex); + if (d->bspTreeDepth == depth) + return; d->bspTreeDepth = depth; d->resetIndex(); } @@ -716,19 +718,41 @@ void QGraphicsSceneBspTreeIndex::sceneRectChanged(const QRectF &rect) update the BSP tree if necessary. */ -void QGraphicsSceneBspTreeIndex::itemChanged(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value) +void QGraphicsSceneBspTreeIndex::itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value) { Q_D(QGraphicsSceneBspTreeIndex); switch (change) { - case QGraphicsItem::ItemZValueChange: - case QGraphicsItem::ItemParentChange: { - d->invalidateSortCache(); - break; + case QGraphicsItem::ItemFlagsChange: { + // Handle ItemIgnoresTransformations + bool ignoredTransform = item->flags() & QGraphicsItem::ItemIgnoresTransformations; + bool willIgnoreTransform = value.toUInt() & QGraphicsItem::ItemIgnoresTransformations; + if (ignoredTransform != willIgnoreTransform) { + QGraphicsItem *thatItem = const_cast(item); + removeItem(thatItem); + addItem(thatItem); } - default: - break; + break; + } + case QGraphicsItem::ItemZValueChange: + d->invalidateSortCache(); + break; + case QGraphicsItem::ItemParentChange: { + d->invalidateSortCache(); + // Handle ItemIgnoresTransformations + QGraphicsItem *newParent = qVariantValue(value); + bool ignoredTransform = item->d_ptr->itemIsUntransformable(); + bool willIgnoreTransform = (item->flags() & QGraphicsItem::ItemIgnoresTransformations) || (newParent && newParent->d_ptr->itemIsUntransformable()); + if (ignoredTransform != willIgnoreTransform) { + QGraphicsItem *thatItem = const_cast(item); + removeItem(thatItem); + addItem(thatItem); + } + break; + } + default: + break; } - return QGraphicsSceneIndex::itemChanged(item, change, value); + return QGraphicsSceneIndex::itemChange(item, change, value); } /*! \reimp diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex.h index 0444a30..504ea8b 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.h +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.h @@ -98,7 +98,7 @@ protected: void prepareBoundingRectChange(const QGraphicsItem *item); void sceneRectChanged(const QRectF &rect); - void itemChanged(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value); + void itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value); private : Q_DECLARE_PRIVATE(QGraphicsSceneBspTreeIndex) diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h index b6f782d..ed12fac 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h @@ -82,6 +82,7 @@ public: QList indexedItems; QList unindexedItems; + QList untransformableItems; QList freeItemIndexes; bool purgePending; @@ -92,8 +93,8 @@ public: void startIndexTimer(int interval = QGRAPHICSSCENE_INDEXTIMER_TIMEOUT); void resetIndex(); - void addToIndex(QGraphicsItem *item); - void removeFromIndex(QGraphicsItem *item); + void addToBspTree(QGraphicsItem *item); + void removeFromBspTree(QGraphicsItem *item); void _q_updateSortCache(); bool sortCacheEnabled; diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index 4ca1c02..eb3abc1 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -61,6 +61,7 @@ #include "qgraphicsscene.h" #include "qgraphicsitem_p.h" #include "qgraphicsscene_p.h" +#include "qgraphicswidget.h" #ifndef QT_NO_GRAPHICSVIEW @@ -69,61 +70,118 @@ QT_BEGIN_NAMESPACE class QGraphicsSceneIndexRectIntersector : public QGraphicsSceneIndexIntersector { public: - QGraphicsSceneIndexRectIntersector(QGraphicsScene *scene) : QGraphicsSceneIndexIntersector(scene) {} - bool intersect(const QRectF &brect) const + bool intersect(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode, + const QTransform &transform, const QTransform &deviceTransform) const { + QRectF brect = item->boundingRect(); + _q_adjustRect(&brect); + + // ### Add test for this (without making things slower?) + Q_UNUSED(exposeRect); + bool keep = true; - if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect) - keep = rect.contains(transform.mapRect(brect)) && rect != brect; - else - keep = rect.intersects(transform.mapRect(brect)); - - if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { - QPainterPath rectPath; - rectPath.addRect(rect); - keep = QGraphicsScenePrivate::get(scene)->itemCollidesWithPath(item, transform.inverted().map(rectPath), mode); + if (QGraphicsItemPrivate::get(item)->itemIsUntransformable()) { + // Untransformable items; map the scene rect to item coordinates. + QRectF itemRect = (deviceTransform * transform.inverted()).mapRect(sceneRect); + if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect) + keep = itemRect.contains(brect) && itemRect != brect; + else + keep = itemRect.intersects(brect); + if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { + QPainterPath itemPath; + itemPath.addRect(itemRect); + keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, itemPath, mode); + } + } else { + if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect) + keep = sceneRect.contains(transform.mapRect(brect)) && sceneRect != brect; + else + keep = sceneRect.intersects(transform.mapRect(brect)); + if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { + QPainterPath rectPath; + rectPath.addRect(sceneRect); + keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, transform.inverted().map(rectPath), mode); + } } return keep; } + + QRectF sceneRect; }; class QGraphicsSceneIndexPointIntersector : public QGraphicsSceneIndexIntersector { public: - QGraphicsSceneIndexPointIntersector(QGraphicsScene *scene) : QGraphicsSceneIndexIntersector(scene) {} - bool intersect(const QRectF &brect) const + bool intersect(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode, + const QTransform &transform, const QTransform &deviceTransform) const { + QRectF brect = item->boundingRect(); + _q_adjustRect(&brect); + + // ### Add test for this (without making things slower?) + Q_UNUSED(exposeRect); + bool keep = false; - if (rect.intersects(transform.mapRect(brect))) - if (item->contains(transform.inverted().map(pos))) - keep = true; - if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { - QPainterPath rectPath; - rectPath.addRect(rect); - keep = QGraphicsScenePrivate::get(scene)->itemCollidesWithPath(item, transform.inverted().map(rectPath), mode); + if (QGraphicsItemPrivate::get(item)->itemIsUntransformable()) { + // Untransformable items; map the scene point to item coordinates. + QPointF itemPoint = (deviceTransform * transform.inverted()).map(scenePoint); + keep = brect.contains(itemPoint); + if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { + QPainterPath pointPath; + pointPath.addRect(QRectF(itemPoint, QSizeF(1, 1))); + keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, pointPath, mode); + } + } else { + QRectF sceneBrect = transform.mapRect(brect); + keep = sceneBrect.contains(scenePoint); + if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { + QPainterPath pointPath; + pointPath.addRect(QRectF(transform.inverted().map(scenePoint), QSizeF(1, 1))); + keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, pointPath, mode); + } } return keep; } - QPointF pos; + + QPointF scenePoint; }; class QGraphicsSceneIndexPathIntersector : public QGraphicsSceneIndexIntersector { public: - QGraphicsSceneIndexPathIntersector(QGraphicsScene *scene) : QGraphicsSceneIndexIntersector(scene) {} - bool intersect(const QRectF &brect) const + bool intersect(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode, + const QTransform &transform, const QTransform &deviceTransform) const { - bool keep = true; - if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect) - keep = rect.contains(transform.mapRect(brect)) && rect != brect; - else - keep = rect.intersects(transform.mapRect(brect)); + QRectF brect = item->boundingRect(); + _q_adjustRect(&brect); + + // ### Add test for this (without making things slower?) + Q_UNUSED(exposeRect); - if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) - keep = QGraphicsScenePrivate::get(scene)->itemCollidesWithPath(item, transform.inverted().map(path), mode); + bool keep = true; + if (QGraphicsItemPrivate::get(item)->itemIsUntransformable()) { + // Untransformable items; map the scene rect to item coordinates. + QPainterPath itemPath = (deviceTransform * transform.inverted()).map(scenePath); + if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect) + keep = itemPath.contains(brect); + else + keep = itemPath.intersects(brect); + if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) + keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, itemPath, mode); + } else { + if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect) + keep = scenePath.contains(transform.mapRect(brect)); + else + keep = scenePath.intersects(transform.mapRect(brect)); + if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { + QPainterPath itemPath = transform.inverted().map(scenePath); + keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, itemPath, mode); + } + } return keep; } - QPainterPath path; + + QPainterPath scenePath; }; /*! @@ -131,9 +189,9 @@ public: */ QGraphicsSceneIndexPrivate::QGraphicsSceneIndexPrivate(QGraphicsScene *scene) : scene(scene) { - pointIntersector = new QGraphicsSceneIndexPointIntersector(scene); - rectIntersector = new QGraphicsSceneIndexRectIntersector(scene); - pathIntersector = new QGraphicsSceneIndexPathIntersector(scene); + pointIntersector = new QGraphicsSceneIndexPointIntersector; + rectIntersector = new QGraphicsSceneIndexRectIntersector; + pathIntersector = new QGraphicsSceneIndexPathIntersector; } /*! @@ -148,19 +206,50 @@ QGraphicsSceneIndexPrivate::~QGraphicsSceneIndexPrivate() /*! \internal + + Checks if item collides with the path and mode, but also checks that if it + doesn't collide, maybe its frame rect will. +*/ +bool QGraphicsSceneIndexPrivate::itemCollidesWithPath(const QGraphicsItem *item, + const QPainterPath &path, + Qt::ItemSelectionMode mode) +{ + if (item->collidesWithPath(path, mode)) + return true; + if (item->isWidget()) { + // Check if this is a window, and if its frame rect collides. + const QGraphicsWidget *widget = static_cast(item); + if (widget->isWindow()) { + QRectF frameRect = widget->windowFrameRect(); + QPainterPath framePath; + framePath.addRect(frameRect); + bool intersects = path.intersects(frameRect); + if (mode == Qt::IntersectsItemShape || mode == Qt::IntersectsItemBoundingRect) + return intersects || path.contains(frameRect.topLeft()) + || framePath.contains(path.elementAt(0)); + return !intersects && path.contains(frameRect.topLeft()); + } + } + return false; +} + +/*! + \internal */ -void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QGraphicsSceneIndexIntersector *intersector, - QList *items, - const QTransform &parentTransform, - const QTransform &viewTransform, - Qt::ItemSelectionMode mode, Qt::SortOrder order, - qreal parentOpacity) const +void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRectF exposeRect, + QGraphicsSceneIndexIntersector *intersector, + QList *items, + const QTransform &parentTransform, + const QTransform &viewTransform, + Qt::ItemSelectionMode mode, Qt::SortOrder order, + qreal parentOpacity) const { // Calculate opacity. qreal opacity; if (item) { if (!item->d_ptr->visible) return; + QGraphicsItem *p = item->d_ptr->parent; bool itemIgnoresParentOpacity = item->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity; bool parentDoesntPropagateOpacity = (p && (p->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)); @@ -186,9 +275,7 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QGr _q_adjustRect(&brect); //We fill the intersector with needed informations - intersector->transform = transform; - intersector->item = item; - keep = intersector->intersect(brect); + keep = intersector->intersect(item, exposeRect, mode, transform, viewTransform); } bool childClip = (item && (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)); @@ -211,7 +298,7 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QGr // Clip. if (childClip) - intersector->rect &= transform.map(item->shape()).controlPointRect(); + exposeRect &= transform.map(item->shape()).controlPointRect(); // Process children behind int i = 0; @@ -220,7 +307,7 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QGr QGraphicsItem *child = children.at(i); if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent)) break; - recursive_items_helper(child, intersector, items, transform, viewTransform, + recursive_items_helper(child, exposeRect, intersector, items, transform, viewTransform, mode, order, opacity); } } @@ -232,7 +319,7 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QGr // Process children in front if (!dontProcessChildren) { for (; i < children.size(); ++i) - recursive_items_helper(children.at(i), intersector, items, transform, viewTransform, + recursive_items_helper(children.at(i), exposeRect, intersector, items, transform, viewTransform, mode, order, opacity); } @@ -311,12 +398,12 @@ QRectF QGraphicsSceneIndex::indexedRect() const QList QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const { + Q_D(const QGraphicsSceneIndex); QList itemList; - d->pointIntersector->mode = mode; - d->pointIntersector->rect = QRectF(pos, QSize(1,1)); - d->pointIntersector->pos = pos; - d->recursive_items_helper(0, d->pointIntersector, &itemList, QTransform(), deviceTransform, mode, order); + d->pointIntersector->scenePoint = pos; + d->recursive_items_helper(0, QRectF(pos, QSizeF(1, 1)), d->pointIntersector, &itemList, + QTransform(), deviceTransform, mode, order); return itemList; } @@ -346,10 +433,11 @@ QList QGraphicsSceneIndex::items(const QRectF &rect, Qt::ItemSe Qt::SortOrder order, const QTransform &deviceTransform) const { Q_D(const QGraphicsSceneIndex); + QRectF exposeRect = rect; + _q_adjustRect(&exposeRect); QList itemList; - d->rectIntersector->mode = mode; - d->rectIntersector->rect = rect; - d->recursive_items_helper(0, d->rectIntersector, &itemList, QTransform(), deviceTransform, mode, order); + d->rectIntersector->sceneRect = rect; + d->recursive_items_helper(0, exposeRect, d->rectIntersector, &itemList, QTransform(), deviceTransform, mode, order); return itemList; } @@ -380,14 +468,12 @@ QList QGraphicsSceneIndex::items(const QPolygonF &polygon, Qt:: { Q_D(const QGraphicsSceneIndex); QList itemList; - QRectF polyRect(polygon.boundingRect()); - _q_adjustRect(&polyRect); - d->pathIntersector->mode = mode; - d->pathIntersector->rect = polyRect; + QRectF exposeRect = polygon.boundingRect(); + _q_adjustRect(&exposeRect); QPainterPath path; path.addPolygon(polygon); - d->pathIntersector->path = path; - d->recursive_items_helper(0, d->pathIntersector, &itemList, QTransform(), deviceTransform, mode, order); + d->pathIntersector->scenePath = path; + d->recursive_items_helper(0, exposeRect, d->pathIntersector, &itemList, QTransform(), deviceTransform, mode, order); return itemList; } @@ -418,12 +504,10 @@ QList QGraphicsSceneIndex::items(const QPainterPath &path, Qt:: { Q_D(const QGraphicsSceneIndex); QList itemList; - QRectF pathRect(path.controlPointRect()); - _q_adjustRect(&pathRect); - d->pathIntersector->mode = mode; - d->pathIntersector->rect = pathRect; - d->pathIntersector->path = path; - d->recursive_items_helper(0, d->pathIntersector, &itemList, QTransform(), deviceTransform, mode, order); + QRectF exposeRect = path.controlPointRect(); + _q_adjustRect(&exposeRect); + d->pathIntersector->scenePath = path; + d->recursive_items_helper(0, exposeRect, d->pathIntersector, &itemList, QTransform(), deviceTransform, mode, order); return itemList; } @@ -508,7 +592,7 @@ void QGraphicsSceneIndex::deleteItem(QGraphicsItem *item) \sa QGraphicsItem::GraphicsItemChange */ -void QGraphicsSceneIndex::itemChanged(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value) +void QGraphicsSceneIndex::itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value) { Q_UNUSED(item); Q_UNUSED(change); diff --git a/src/gui/graphicsview/qgraphicssceneindex.h b/src/gui/graphicsview/qgraphicssceneindex.h index ddce9d4..25ece04 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.h +++ b/src/gui/graphicsview/qgraphicssceneindex.h @@ -104,7 +104,7 @@ protected: virtual void removeItem(QGraphicsItem *item) = 0; virtual void deleteItem(QGraphicsItem *item); - virtual void itemChanged(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange, const QVariant &value); + virtual void itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange, const QVariant &value); virtual void prepareBoundingRectChange(const QGraphicsItem *item); virtual void sceneRectChanged(const QRectF &rect); diff --git a/src/gui/graphicsview/qgraphicssceneindex_p.h b/src/gui/graphicsview/qgraphicssceneindex_p.h index d0d181b..576ee98 100644 --- a/src/gui/graphicsview/qgraphicssceneindex_p.h +++ b/src/gui/graphicsview/qgraphicssceneindex_p.h @@ -75,9 +75,12 @@ public: QGraphicsSceneIndexPrivate(QGraphicsScene *scene); ~QGraphicsSceneIndexPrivate(); - void recursive_items_helper(QGraphicsItem *item, QGraphicsSceneIndexIntersector *intersector, QList *items, - const QTransform &parentTransform, const QTransform &viewTransform, - Qt::ItemSelectionMode mode, Qt::SortOrder order, qreal parentOpacity = 1.0) const; + static bool itemCollidesWithPath(const QGraphicsItem *item, const QPainterPath &path, Qt::ItemSelectionMode mode); + + void recursive_items_helper(QGraphicsItem *item, QRectF exposeRect, + QGraphicsSceneIndexIntersector *intersector, QList *items, + const QTransform &parentTransform, const QTransform &viewTransform, + Qt::ItemSelectionMode mode, Qt::SortOrder order, qreal parentOpacity = 1.0) const; QGraphicsScene *scene; QGraphicsSceneIndexPointIntersector *pointIntersector; QGraphicsSceneIndexRectIntersector *rectIntersector; @@ -87,14 +90,10 @@ public: class QGraphicsSceneIndexIntersector { public: - QGraphicsSceneIndexIntersector(QGraphicsScene *scene) : scene(scene) { } + QGraphicsSceneIndexIntersector() { } virtual ~QGraphicsSceneIndexIntersector() { } - virtual bool intersect(const QRectF &rect) const = 0; - Qt::ItemSelectionMode mode; - QGraphicsItem *item; - QGraphicsScene *scene; - QRectF rect; - QTransform transform; + virtual bool intersect(const QGraphicsItem *item, const QRectF &exposeRect, Qt::ItemSelectionMode mode, + const QTransform &transform, const QTransform &deviceTransform) const = 0; }; QT_END_NAMESPACE diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 8c40878..a1e6d9c 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -914,44 +914,32 @@ extern QPainterPath qt_regionToPath(const QRegion ®ion); is at risk of painting 1 pixel outside the bounding rect. Therefore we must search for items with an adjustment of (-1, -1, 1, 1). */ -QList QGraphicsViewPrivate::findItems(const QRegion &exposedRegion, bool *allItems) const +QList QGraphicsViewPrivate::findItems(const QRegion &exposedRegion, bool *allItems, + const QTransform &viewTransform) const { Q_Q(const QGraphicsView); // Step 1) If all items are contained within the expose region, then - // return a list of all visible items. + // return a list of all visible items. ### the scene's growing bounding + // rect does not take into account untransformable items. const QRectF exposedRegionSceneBounds = q->mapToScene(exposedRegion.boundingRect().adjusted(-1, -1, 1, 1)) .boundingRect(); if (exposedRegionSceneBounds.contains(scene->d_func()->growingItemsBoundingRect)) { Q_ASSERT(allItems); *allItems = true; - // All items are guaranteed within the exposed region, don't bother using the index. - QList itemList(scene->d_func()->index->items(Qt::DescendingOrder)); - int i = 0; - while (i < itemList.size()) { - const QGraphicsItem *item = itemList.at(i); - // But we only want to include items that are visible - // The following check is basically the same as item->d_ptr->isInvisible(), except - // that we don't check whether the item clips children to shape or propagates its - // opacity (we loop through all items, so those checks are wrong in this context). - if (!item->isVisible() || item->d_ptr->isClippedAway() || item->d_ptr->isFullyTransparent()) - itemList.removeAt(i); - else - ++i; - } - return itemList; + // All items are guaranteed within the exposed region. + return scene->items(Qt::DescendingOrder); } // Step 2) If the expose region is a simple rect and the view is only // translated or scaled, search for items using // QGraphicsScene::items(QRectF). - bool simpleRectLookup = (scene->d_func()->largestUntransformableItem.isNull() - && exposedRegion.numRects() == 1 && matrix.type() <= QTransform::TxScale); + bool simpleRectLookup = exposedRegion.numRects() == 1 && matrix.type() <= QTransform::TxScale; if (simpleRectLookup) { - return scene->d_func()->index->items(exposedRegionSceneBounds, - Qt::IntersectsItemBoundingRect, - Qt::DescendingOrder); + return scene->items(exposedRegionSceneBounds, + Qt::IntersectsItemBoundingRect, + Qt::DescendingOrder, viewTransform); } // If the region is complex or the view has a complex transform, adjust @@ -961,16 +949,9 @@ QList QGraphicsViewPrivate::findItems(const QRegion &exposedReg foreach (const QRect &r, exposedRegion.rects()) adjustedRegion += r.adjusted(-1, -1, 1, 1); - const QPainterPath exposedPath(qt_regionToPath(adjustedRegion)); - if (scene->d_func()->largestUntransformableItem.isNull()) { - const QPainterPath exposedScenePath(q->mapToScene(exposedPath)); - return scene->d_func()->index->items(exposedScenePath, - Qt::IntersectsItemBoundingRect, - Qt::DescendingOrder); - } - - // NB! Path must be in viewport coordinates. - return itemsInArea(exposedPath, Qt::IntersectsItemBoundingRect, Qt::DescendingOrder); + const QPainterPath exposedScenePath(q->mapToScene(qt_regionToPath(adjustedRegion))); + return scene->items(exposedScenePath, Qt::IntersectsItemBoundingRect, + Qt::DescendingOrder, viewTransform); } /*! @@ -1875,6 +1856,8 @@ void QGraphicsView::fitInView(const QGraphicsItem *item, Qt::AspectRatioMode asp void QGraphicsView::render(QPainter *painter, const QRectF &target, const QRect &source, Qt::AspectRatioMode aspectRatioMode) { + // ### Switch to using the recursive rendering algorithm instead. + Q_D(QGraphicsView); if (!d->scene || !(painter && painter->isActive())) return; @@ -1972,67 +1955,6 @@ QList QGraphicsView::items() const } /*! - Returns all items in the area \a path, which is in viewport coordinates, - also taking untransformable items into consideration. This function is - considerably slower than just checking the scene directly. There is - certainly room for improvement. -*/ -QList QGraphicsViewPrivate::itemsInArea(const QPainterPath &path, - Qt::ItemSelectionMode mode, - Qt::SortOrder order) const -{ - Q_Q(const QGraphicsView); - - // Determine the size of the largest untransformable subtree of children - // mapped to scene coordinates. - QRectF untr = scene->d_func()->largestUntransformableItem; - QRectF ltri = matrix.inverted().mapRect(untr); - ltri.adjust(-untr.width(), -untr.height(), untr.width(), untr.height()); - - QRectF rect = path.controlPointRect(); - - // Find all possible items in the relevant area. - // ### Improve this algorithm; it might be searching a too large area. - QRectF adjustedRect = q->mapToScene(rect.adjusted(-1, -1, 1, 1).toRect()).boundingRect(); - adjustedRect.adjust(-ltri.width(), -ltri.height(), ltri.width(), ltri.height()); - - // First build a (potentially large) list of all items in the vicinity - // that might be untransformable. - QList allCandidates = scene->d_func()->index->estimateItems(adjustedRect, order, q->transform()); - - // Then find the minimal list of items that are inside \a path, and - // convert it to a set. - QList regularCandidates = scene->items(q->mapToScene(path), mode, order, q->transform()); - QSet candSet = QSet::fromList(regularCandidates); - - QTransform viewMatrix = q->viewportTransform(); - - QList result; - - //### this will disapear - - // Run through all candidates and keep all items that are in candSet, or - // are untransformable and collide with \a path. ### We can improve this - // algorithm. - QList::Iterator it = allCandidates.begin(); - while (it != allCandidates.end()) { - QGraphicsItem *item = *it; - if (item->d_ptr->itemIsUntransformable()) { - // Check if this untransformable item collides with the - // original selection rect. - QTransform itemTransform = item->deviceTransform(viewMatrix); - if (QGraphicsScenePrivate::itemCollidesWithPath(item, itemTransform.inverted().map(path), mode)) - result << item; - } else { - if (candSet.contains(item)) - result << item; - } - ++it; - } - return result; -} - -/*! Returns a list of all the items at the position \a pos in the view. The items are listed in descending Z order (i.e., the first item in the list is the top-most item, and the last item is the bottom-most item). \a pos @@ -2051,17 +1973,22 @@ QList QGraphicsView::items(const QPoint &pos) const Q_D(const QGraphicsView); if (!d->scene) return QList(); - if (d->scene->d_func()->largestUntransformableItem.isNull()) { - if ((d->identityMatrix || d->matrix.type() <= QTransform::TxScale)) { - QTransform xinv = viewportTransform().inverted(); - return d->scene->items(xinv.mapRect(QRectF(pos.x(), pos.y(), 1, 1))); - } - return d->scene->items(mapToScene(pos.x(), pos.y(), 1, 1)); + // ### Unify these two, and use the items(QPointF) version in + // QGraphicsScene instead. The scene items function could use the viewport + // transform to map the point to a rect/polygon. + if ((d->identityMatrix || d->matrix.type() <= QTransform::TxScale)) { + // Use the rect version + QTransform xinv = viewportTransform().inverted(); + return d->scene->items(xinv.mapRect(QRectF(pos.x(), pos.y(), 1, 1)), + Qt::IntersectsItemShape, + Qt::AscendingOrder, + viewportTransform()); } - - QPainterPath path; - path.addRect(QRectF(pos.x(), pos.y(), 1, 1)); - return d->itemsInArea(path); + // Use the polygon version + return d->scene->items(mapToScene(pos.x(), pos.y(), 1, 1), + Qt::IntersectsItemShape, + Qt::AscendingOrder, + viewportTransform()); } /*! @@ -2088,12 +2015,7 @@ QList QGraphicsView::items(const QRect &rect, Qt::ItemSelection Q_D(const QGraphicsView); if (!d->scene) return QList(); - if (d->scene->d_func()->largestUntransformableItem.isNull()) - return d->scene->items(mapToScene(rect), mode); - - QPainterPath path; - path.addRect(rect); - return d->itemsInArea(path); + return d->scene->items(mapToScene(rect), mode, Qt::AscendingOrder, viewportTransform()); } /*! @@ -2121,13 +2043,7 @@ QList QGraphicsView::items(const QPolygon &polygon, Qt::ItemSel Q_D(const QGraphicsView); if (!d->scene) return QList(); - if (d->scene->d_func()->largestUntransformableItem.isNull()) - return d->scene->items(mapToScene(polygon), mode); - - QPainterPath path; - path.addPolygon(polygon); - path.closeSubpath(); - return d->itemsInArea(path); + return d->scene->items(mapToScene(polygon), mode, Qt::AscendingOrder, viewportTransform()); } /*! @@ -2147,9 +2063,7 @@ QList QGraphicsView::items(const QPainterPath &path, Qt::ItemSe Q_D(const QGraphicsView); if (!d->scene) return QList(); - if (d->scene->d_func()->largestUntransformableItem.isNull()) - return d->scene->items(mapToScene(path), mode); - return d->itemsInArea(path); + return d->scene->items(mapToScene(path), mode, Qt::AscendingOrder, viewportTransform()); } /*! @@ -2168,7 +2082,9 @@ QGraphicsItem *QGraphicsView::itemAt(const QPoint &pos) const Q_D(const QGraphicsView); if (!d->scene) return 0; - QList itemsAtPos = items(pos); + // ### Use QGraphicsScene::itemAt() instead. + QList itemsAtPos = d->scene->items(pos, Qt::IntersectsItemShape, Qt::AscendingOrder, + viewportTransform()); return itemsAtPos.isEmpty() ? 0 : itemsAtPos.first(); } @@ -3073,7 +2989,8 @@ void QGraphicsView::mouseMoveEvent(QMouseEvent *event) selectionArea.addPolygon(mapToScene(d->rubberBandRect)); selectionArea.closeSubpath(); if (d->scene) - d->scene->setSelectionArea(selectionArea, d->rubberBandSelectionMode); + d->scene->setSelectionArea(selectionArea, d->rubberBandSelectionMode, + viewportTransform()); return; } } else @@ -3280,7 +3197,7 @@ void QGraphicsView::paintEvent(QPaintEvent *event) } else { // Find all exposed items bool allItems = false; - QList itemList = d->findItems(d->exposedRegion, &allItems); + QList itemList = d->findItems(d->exposedRegion, &allItems, viewTransform); if (!itemList.isEmpty()) { // Generate the style options. diff --git a/src/gui/graphicsview/qgraphicsview_p.h b/src/gui/graphicsview/qgraphicsview_p.h index fac7bf9..760f54e 100644 --- a/src/gui/graphicsview/qgraphicsview_p.h +++ b/src/gui/graphicsview/qgraphicsview_p.h @@ -84,10 +84,6 @@ public: qint64 horizontalScroll() const; qint64 verticalScroll() const; - QList itemsInArea(const QPainterPath &path, - Qt::ItemSelectionMode mode = Qt::IntersectsItemShape, - Qt::SortOrder = Qt::AscendingOrder) const; - QPointF mousePressItemPoint; QPointF mousePressScenePoint; QPoint mousePressViewPoint; @@ -176,7 +172,8 @@ public: bool updateSceneSlotReimplementedChecked; QRegion exposedRegion; - QList findItems(const QRegion &exposedRegion, bool *allItems) const; + QList findItems(const QRegion &exposedRegion, bool *allItems, + const QTransform &viewTransform) const; }; QT_END_NAMESPACE -- cgit v0.12 From b8ca90d6ca745915455f044f967a345bab7a910e Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Thu, 18 Jun 2009 14:49:24 +0200 Subject: Move QGraphicsSceneIndex into private headers (=> _p.h). We'd like to keep this API private for now. Reviewed-by: Alexis --- src/gui/graphicsview/graphicsview.pri | 57 +++++---- src/gui/graphicsview/qgraphicsscene.cpp | 5 +- src/gui/graphicsview/qgraphicsscene_p.h | 2 +- .../graphicsview/qgraphicsscenebsptreeindex.cpp | 4 +- src/gui/graphicsview/qgraphicsscenebsptreeindex.h | 2 +- src/gui/graphicsview/qgraphicssceneindex.cpp | 5 +- src/gui/graphicsview/qgraphicssceneindex.h | 129 --------------------- src/gui/graphicsview/qgraphicssceneindex_p.h | 79 +++++++++++-- src/gui/graphicsview/qgraphicsscenelinearindex.h | 2 +- 9 files changed, 106 insertions(+), 179 deletions(-) delete mode 100644 src/gui/graphicsview/qgraphicssceneindex.h diff --git a/src/gui/graphicsview/graphicsview.pri b/src/gui/graphicsview/graphicsview.pri index 5ac1c54..2d8f37e 100644 --- a/src/gui/graphicsview/graphicsview.pri +++ b/src/gui/graphicsview/graphicsview.pri @@ -1,46 +1,43 @@ # Qt graphicsview module -HEADERS += graphicsview/qgraphicsitem.h \ +HEADERS += graphicsview/qgraphicsgridlayout.h \ + graphicsview/qgraphicsitem.h \ graphicsview/qgraphicsitem_p.h \ graphicsview/qgraphicsitemanimation.h \ + graphicsview/qgraphicslayout.h \ + graphicsview/qgraphicslayout_p.h \ + graphicsview/qgraphicslayoutitem.h \ + graphicsview/qgraphicslayoutitem_p.h \ + graphicsview/qgraphicslinearlayout.h \ + graphicsview/qgraphicsproxywidget.h \ graphicsview/qgraphicsscene.h \ - graphicsview/qgraphicsscene_p.h \ graphicsview/qgraphicsscene_bsp_p.h \ - graphicsview/qgraphicsscenelinearindex.h \ - graphicsview/qgraphicssceneindex.h \ - graphicsview/qgraphicssceneindex_p.h \ + graphicsview/qgraphicsscene_p.h \ graphicsview/qgraphicsscenebsptreeindex.h \ graphicsview/qgraphicsscenebsptreeindex_p.h \ graphicsview/qgraphicssceneevent.h \ + graphicsview/qgraphicssceneindex_p.h \ + graphicsview/qgraphicsscenelinearindex.h \ + graphicsview/qgraphicsview.h \ graphicsview/qgraphicsview_p.h \ - graphicsview/qgraphicsview.h -SOURCES += graphicsview/qgraphicsitem.cpp \ - graphicsview/qgraphicsitemanimation.cpp \ - graphicsview/qgraphicsscene.cpp \ - graphicsview/qgraphicsscene_bsp.cpp \ - graphicsview/qgraphicsscenebsptreeindex.cpp \ - graphicsview/qgraphicsscenelinearindex.cpp \ - graphicsview/qgraphicssceneindex.cpp \ - graphicsview/qgraphicssceneevent.cpp \ - graphicsview/qgraphicsview.cpp - - -# Widgets on the canvas -HEADERS += graphicsview/qgraphicslayout.h \ - graphicsview/qgraphicslayout_p.h \ - graphicsview/qgraphicslayoutitem.h \ - graphicsview/qgraphicslayoutitem_p.h \ - graphicsview/qgraphicslinearlayout.h \ graphicsview/qgraphicswidget.h \ graphicsview/qgraphicswidget_p.h \ - graphicsview/qgridlayoutengine_p.h \ - graphicsview/qgraphicsproxywidget.h \ - graphicsview/qgraphicsgridlayout.h -SOURCES += graphicsview/qgraphicslayout.cpp \ + graphicsview/qgridlayoutengine_p.h + +SOURCES += graphicsview/qgraphicsgridlayout.cpp \ + graphicsview/qgraphicsitem.cpp \ + graphicsview/qgraphicsitemanimation.cpp \ + graphicsview/qgraphicslayout.cpp \ graphicsview/qgraphicslayout_p.cpp \ graphicsview/qgraphicslayoutitem.cpp \ graphicsview/qgraphicslinearlayout.cpp \ + graphicsview/qgraphicsproxywidget.cpp \ + graphicsview/qgraphicsscene.cpp \ + graphicsview/qgraphicsscene_bsp.cpp \ + graphicsview/qgraphicsscenebsptreeindex.cpp \ + graphicsview/qgraphicssceneevent.cpp \ + graphicsview/qgraphicssceneindex.cpp \ + graphicsview/qgraphicsscenelinearindex.cpp \ + graphicsview/qgraphicsview.cpp \ graphicsview/qgraphicswidget.cpp \ graphicsview/qgraphicswidget_p.cpp \ - graphicsview/qgridlayoutengine.cpp \ - graphicsview/qgraphicsproxywidget.cpp \ - graphicsview/qgraphicsgridlayout.cpp + graphicsview/qgridlayoutengine.cpp diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 55f0f20..9d224b1 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -217,7 +217,6 @@ #include "qgraphicsview_p.h" #include "qgraphicswidget.h" #include "qgraphicswidget_p.h" -#include "qgraphicssceneindex.h" #include "qgraphicsscenebsptreeindex.h" #include "qgraphicsscenelinearindex.h" @@ -244,6 +243,7 @@ #include #include #include +#include #include #ifdef Q_WS_X11 #include @@ -772,6 +772,7 @@ QList QGraphicsScenePrivate::itemsAtPosition(const QPoint &scre const QPointF &scenePos, QWidget *widget) const { + Q_UNUSED(screenPos); Q_Q(const QGraphicsScene); QGraphicsView *view = widget ? qobject_cast(widget->parentWidget()) : 0; return q->items(scenePos, Qt::IntersectsItemShape, Qt::AscendingOrder, @@ -1806,7 +1807,7 @@ void QGraphicsScene::setSelectionArea(const QPainterPath &path) */ void QGraphicsScene::setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode mode) { - setSelectionArea(path, Qt::IntersectsItemShape, QTransform()); + setSelectionArea(path, mode, QTransform()); } /*! diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index a081e04..fd25283 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -58,7 +58,6 @@ #if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW #include "qgraphicsscenebsptreeindex_p.h" -#include "qgraphicssceneindex.h" #include "qgraphicsview.h" #include "qgraphicsitem_p.h" @@ -74,6 +73,7 @@ QT_BEGIN_NAMESPACE +class QGraphicsSceneIndex; class QGraphicsView; class QGraphicsWidget; diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp index 40cafa6..54bf09b 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -80,12 +80,12 @@ #ifndef QT_NO_GRAPHICSVIEW #include "qgraphicsscenebsptreeindex_p.h" -#include "qgraphicssceneindex_p.h" #include "qgraphicsitem_p.h" #include "qgraphicsscene_p.h" -#include +#include +#include #include QT_BEGIN_NAMESPACE diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex.h index 504ea8b..f3c77d3 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.h +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.h @@ -67,7 +67,7 @@ QT_MODULE(Gui) #include #include #include -#include +#include #include "qgraphicsscene_bsp_p.h" diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index eb3abc1..8d7581f 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -56,12 +56,11 @@ \sa QGraphicsScene, QGraphicsView */ -#include "qgraphicssceneindex.h" -#include "qgraphicssceneindex_p.h" #include "qgraphicsscene.h" #include "qgraphicsitem_p.h" #include "qgraphicsscene_p.h" #include "qgraphicswidget.h" +#include #ifndef QT_NO_GRAPHICSVIEW @@ -621,6 +620,6 @@ void QGraphicsSceneIndex::sceneRectChanged(const QRectF &rect) QT_END_NAMESPACE -#include "moc_qgraphicssceneindex.cpp" +#include "moc_qgraphicssceneindex_p.cpp" #endif // QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicssceneindex.h b/src/gui/graphicsview/qgraphicssceneindex.h deleted file mode 100644 index 25ece04..0000000 --- a/src/gui/graphicsview/qgraphicssceneindex.h +++ /dev/null @@ -1,129 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRAPHICSSCENEINDEX_H -#define QGRAPHICSSCENEINDEX_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header -// file may change from version to version without notice, or even be removed. -// -// We mean it. -// - -#include -#include -#include -#include - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Gui) - -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - -class QGraphicsSceneIndexPrivate; -class QGraphicsScene; -class QRectF; -class QPointF; -template class QList; - -class Q_AUTOTEST_EXPORT QGraphicsSceneIndex: public QObject -{ - Q_OBJECT - -public: - QGraphicsSceneIndex(QGraphicsScene *scene = 0); - virtual ~QGraphicsSceneIndex(); - - QGraphicsScene *scene() const; - - virtual QRectF indexedRect() const; - - virtual QList items(Qt::SortOrder order = Qt::AscendingOrder) const = 0; - virtual QList items(const QPointF &pos, Qt::ItemSelectionMode mode, - Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; - virtual QList items(const QRectF &rect, Qt::ItemSelectionMode mode, - Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; - virtual QList items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, - Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; - virtual QList items(const QPainterPath &path, Qt::ItemSelectionMode mode, - Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; - virtual QList estimateItems(const QPointF &point, - Qt::SortOrder order, const QTransform &deviceTransform) const; - virtual QList estimateItems(const QRectF &rect, - Qt::SortOrder order, const QTransform &deviceTransform) const = 0; - -protected: - virtual void clear(); - virtual void addItem(QGraphicsItem *item) = 0; - virtual void removeItem(QGraphicsItem *item) = 0; - virtual void deleteItem(QGraphicsItem *item); - - virtual void itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange, const QVariant &value); - virtual void prepareBoundingRectChange(const QGraphicsItem *item); - virtual void sceneRectChanged(const QRectF &rect); - - QGraphicsSceneIndex(QObjectPrivate &dd, QGraphicsScene *scene); - - friend class QGraphicsScene; - friend class QGraphicsScenePrivate; - friend class QGraphicsItem; - friend class QGraphicsItemPrivate; - friend class QGraphicsSceneBspTreeIndex; -private: - Q_DISABLE_COPY(QGraphicsSceneIndex) - Q_DECLARE_PRIVATE(QGraphicsSceneIndex) -}; - -#endif // QT_NO_GRAPHICSVIEW - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QGRAPHICSSCENEINDEX_H diff --git a/src/gui/graphicsview/qgraphicssceneindex_p.h b/src/gui/graphicsview/qgraphicssceneindex_p.h index 576ee98..85a1140 100644 --- a/src/gui/graphicsview/qgraphicssceneindex_p.h +++ b/src/gui/graphicsview/qgraphicssceneindex_p.h @@ -39,8 +39,8 @@ ** ****************************************************************************/ -#ifndef QGRAPHICSSCENEINDEX_P_H -#define QGRAPHICSSCENEINDEX_P_H +#ifndef QGRAPHICSSCENEINDEX_H +#define QGRAPHICSSCENEINDEX_H // // W A R N I N G @@ -53,20 +53,77 @@ // We mean it. // -#include "qgraphicssceneindex.h" - -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - +#include +#include +#include +#include #include -#include + +QT_BEGIN_HEADER QT_BEGIN_NAMESPACE +QT_MODULE(Gui) + +#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW + class QGraphicsScene; class QGraphicsSceneIndexIntersector; -class QGraphicsSceneIndexRectIntersector; class QGraphicsSceneIndexPointIntersector; +class QGraphicsSceneIndexRectIntersector; class QGraphicsSceneIndexPathIntersector; +class QGraphicsSceneIndexPrivate; +class QPointF; +class QRectF; +template class QList; + +class Q_AUTOTEST_EXPORT QGraphicsSceneIndex : public QObject +{ + Q_OBJECT + +public: + QGraphicsSceneIndex(QGraphicsScene *scene = 0); + virtual ~QGraphicsSceneIndex(); + + QGraphicsScene *scene() const; + + virtual QRectF indexedRect() const; + + virtual QList items(Qt::SortOrder order = Qt::AscendingOrder) const = 0; + virtual QList items(const QPointF &pos, Qt::ItemSelectionMode mode, + Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; + virtual QList items(const QRectF &rect, Qt::ItemSelectionMode mode, + Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; + virtual QList items(const QPolygonF &polygon, Qt::ItemSelectionMode mode, + Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; + virtual QList items(const QPainterPath &path, Qt::ItemSelectionMode mode, + Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; + virtual QList estimateItems(const QPointF &point, + Qt::SortOrder order, const QTransform &deviceTransform) const; + virtual QList estimateItems(const QRectF &rect, + Qt::SortOrder order, const QTransform &deviceTransform) const = 0; + +protected: + virtual void clear(); + virtual void addItem(QGraphicsItem *item) = 0; + virtual void removeItem(QGraphicsItem *item) = 0; + virtual void deleteItem(QGraphicsItem *item); + + virtual void itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange, const QVariant &value); + virtual void prepareBoundingRectChange(const QGraphicsItem *item); + virtual void sceneRectChanged(const QRectF &rect); + + QGraphicsSceneIndex(QObjectPrivate &dd, QGraphicsScene *scene); + + friend class QGraphicsScene; + friend class QGraphicsScenePrivate; + friend class QGraphicsItem; + friend class QGraphicsItemPrivate; + friend class QGraphicsSceneBspTreeIndex; +private: + Q_DISABLE_COPY(QGraphicsSceneIndex) + Q_DECLARE_PRIVATE(QGraphicsSceneIndex) +}; class QGraphicsSceneIndexPrivate : public QObjectPrivate { @@ -96,8 +153,10 @@ public: const QTransform &transform, const QTransform &deviceTransform) const = 0; }; +#endif // QT_NO_GRAPHICSVIEW + QT_END_NAMESPACE -#endif // QGRAPHICSSCENEINDEX_P_H +QT_END_HEADER -#endif +#endif // QGRAPHICSSCENEINDEX_H diff --git a/src/gui/graphicsview/qgraphicsscenelinearindex.h b/src/gui/graphicsview/qgraphicsscenelinearindex.h index b793d98..a5327ef 100644 --- a/src/gui/graphicsview/qgraphicsscenelinearindex.h +++ b/src/gui/graphicsview/qgraphicsscenelinearindex.h @@ -65,8 +65,8 @@ QT_MODULE(Gui) #include #include -#include #include +#include class Q_AUTOTEST_EXPORT QGraphicsSceneLinearIndex : public QGraphicsSceneIndex { -- cgit v0.12 From d49fd874258c055b54b122a0c1f6f10ee20f11ea Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Thu, 18 Jun 2009 14:52:47 +0200 Subject: Move QGraphicsSceneLinearIndex into private headers (=> _p.h). We want to keep this as private API for now. Reviewed-by: Alexis --- src/gui/graphicsview/graphicsview.pri | 2 +- src/gui/graphicsview/qgraphicsscene.cpp | 2 +- src/gui/graphicsview/qgraphicsscenelinearindex.cpp | 4 +- src/gui/graphicsview/qgraphicsscenelinearindex.h | 124 --------------------- src/gui/graphicsview/qgraphicsscenelinearindex_p.h | 124 +++++++++++++++++++++ 5 files changed, 128 insertions(+), 128 deletions(-) delete mode 100644 src/gui/graphicsview/qgraphicsscenelinearindex.h create mode 100644 src/gui/graphicsview/qgraphicsscenelinearindex_p.h diff --git a/src/gui/graphicsview/graphicsview.pri b/src/gui/graphicsview/graphicsview.pri index 2d8f37e..5981ce5 100644 --- a/src/gui/graphicsview/graphicsview.pri +++ b/src/gui/graphicsview/graphicsview.pri @@ -16,7 +16,7 @@ HEADERS += graphicsview/qgraphicsgridlayout.h \ graphicsview/qgraphicsscenebsptreeindex_p.h \ graphicsview/qgraphicssceneevent.h \ graphicsview/qgraphicssceneindex_p.h \ - graphicsview/qgraphicsscenelinearindex.h \ + graphicsview/qgraphicsscenelinearindex_p.h \ graphicsview/qgraphicsview.h \ graphicsview/qgraphicsview_p.h \ graphicsview/qgraphicswidget.h \ diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 9d224b1..e004917 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -218,7 +218,7 @@ #include "qgraphicswidget.h" #include "qgraphicswidget_p.h" #include "qgraphicsscenebsptreeindex.h" -#include "qgraphicsscenelinearindex.h" +#include #include #include diff --git a/src/gui/graphicsview/qgraphicsscenelinearindex.cpp b/src/gui/graphicsview/qgraphicsscenelinearindex.cpp index 5504493..694062b 100644 --- a/src/gui/graphicsview/qgraphicsscenelinearindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenelinearindex.cpp @@ -1,5 +1,3 @@ -#include "qgraphicsscenelinearindex.h" - /*! \class QGraphicsSceneLinearIndex \brief The QGraphicsSceneLinearIndex class provides an implementation of @@ -16,6 +14,8 @@ \sa QGraphicsScene, QGraphicsView, QGraphicsSceneIndex, QGraphicsSceneBspTreeIndex */ +#include + /*! \fn QGraphicsSceneLinearIndex::QGraphicsSceneLinearIndex(QGraphicsScene *scene = 0): diff --git a/src/gui/graphicsview/qgraphicsscenelinearindex.h b/src/gui/graphicsview/qgraphicsscenelinearindex.h deleted file mode 100644 index a5327ef..0000000 --- a/src/gui/graphicsview/qgraphicsscenelinearindex.h +++ /dev/null @@ -1,124 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QGRAPHICSSCENELINEARINDEX_H -#define QGRAPHICSSCENELINEARINDEX_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Gui) - -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - -#include -#include -#include -#include - -class Q_AUTOTEST_EXPORT QGraphicsSceneLinearIndex : public QGraphicsSceneIndex -{ - Q_OBJECT - -public: - QGraphicsSceneLinearIndex(QGraphicsScene *scene = 0): QGraphicsSceneIndex(scene) - { - } - - QList items(Qt::SortOrder order = Qt::AscendingOrder) const { - Q_UNUSED(order); - return m_items; - } - - virtual QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const { - Q_UNUSED(rect); - Q_UNUSED(order); - Q_UNUSED(deviceTransform); - return m_items; - } - - virtual QRectF indexedRect() const { - return m_sceneRect; - } - -protected : - void sceneRectChanged(const QRectF &rect) { - m_sceneRect = rect; - } - - virtual void clear() { - m_items.clear(); - } - - virtual void addItem(QGraphicsItem *item) { - m_items << item; - } - - virtual void removeItem(QGraphicsItem *item) { - m_items.removeAll(item); - } - -private: - QRectF m_sceneRect; - QList m_items; -}; - -#endif // QT_NO_GRAPHICSVIEW - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QGRAPHICSSCENELINEARINDEX_H diff --git a/src/gui/graphicsview/qgraphicsscenelinearindex_p.h b/src/gui/graphicsview/qgraphicsscenelinearindex_p.h new file mode 100644 index 0000000..a5327ef --- /dev/null +++ b/src/gui/graphicsview/qgraphicsscenelinearindex_p.h @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGRAPHICSSCENELINEARINDEX_H +#define QGRAPHICSSCENELINEARINDEX_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW + +#include +#include +#include +#include + +class Q_AUTOTEST_EXPORT QGraphicsSceneLinearIndex : public QGraphicsSceneIndex +{ + Q_OBJECT + +public: + QGraphicsSceneLinearIndex(QGraphicsScene *scene = 0): QGraphicsSceneIndex(scene) + { + } + + QList items(Qt::SortOrder order = Qt::AscendingOrder) const { + Q_UNUSED(order); + return m_items; + } + + virtual QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const { + Q_UNUSED(rect); + Q_UNUSED(order); + Q_UNUSED(deviceTransform); + return m_items; + } + + virtual QRectF indexedRect() const { + return m_sceneRect; + } + +protected : + void sceneRectChanged(const QRectF &rect) { + m_sceneRect = rect; + } + + virtual void clear() { + m_items.clear(); + } + + virtual void addItem(QGraphicsItem *item) { + m_items << item; + } + + virtual void removeItem(QGraphicsItem *item) { + m_items.removeAll(item); + } + +private: + QRectF m_sceneRect; + QList m_items; +}; + +#endif // QT_NO_GRAPHICSVIEW + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QGRAPHICSSCENELINEARINDEX_H -- cgit v0.12 From 734cc7dd63147f80cd4794351b9124f8d6eb88fe Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Thu, 18 Jun 2009 14:56:59 +0200 Subject: Move QGraphicsSceneBspTreeIndex into private headers (=> _p.h). We'll keep this as private API for now. Reviewed-by: Alexis --- src/gui/graphicsview/graphicsview.pri | 1 - src/gui/graphicsview/qgraphicsscene.cpp | 2 +- .../graphicsview/qgraphicsscenebsptreeindex.cpp | 10 +- src/gui/graphicsview/qgraphicsscenebsptreeindex.h | 119 --------------------- .../graphicsview/qgraphicsscenebsptreeindex_p.h | 66 ++++++++++-- 5 files changed, 61 insertions(+), 137 deletions(-) delete mode 100644 src/gui/graphicsview/qgraphicsscenebsptreeindex.h diff --git a/src/gui/graphicsview/graphicsview.pri b/src/gui/graphicsview/graphicsview.pri index 5981ce5..0c0747e 100644 --- a/src/gui/graphicsview/graphicsview.pri +++ b/src/gui/graphicsview/graphicsview.pri @@ -12,7 +12,6 @@ HEADERS += graphicsview/qgraphicsgridlayout.h \ graphicsview/qgraphicsscene.h \ graphicsview/qgraphicsscene_bsp_p.h \ graphicsview/qgraphicsscene_p.h \ - graphicsview/qgraphicsscenebsptreeindex.h \ graphicsview/qgraphicsscenebsptreeindex_p.h \ graphicsview/qgraphicssceneevent.h \ graphicsview/qgraphicssceneindex_p.h \ diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index e004917..28dd3be 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -217,7 +217,7 @@ #include "qgraphicsview_p.h" #include "qgraphicswidget.h" #include "qgraphicswidget_p.h" -#include "qgraphicsscenebsptreeindex.h" +#include #include #include diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp index 54bf09b..27b5514 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -75,14 +75,10 @@ \sa QGraphicsScene, QGraphicsView, QGraphicsSceneIndex */ -#include "qgraphicsscenebsptreeindex.h" - #ifndef QT_NO_GRAPHICSVIEW -#include "qgraphicsscenebsptreeindex_p.h" -#include "qgraphicsitem_p.h" -#include "qgraphicsscene_p.h" - +#include +#include #include #include @@ -783,7 +779,7 @@ bool QGraphicsSceneBspTreeIndex::event(QEvent *event) QT_END_NAMESPACE -#include "moc_qgraphicsscenebsptreeindex.cpp" +#include "moc_qgraphicsscenebsptreeindex_p.cpp" #endif // QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex.h deleted file mode 100644 index f3c77d3..0000000 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.h +++ /dev/null @@ -1,119 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header -// file may change from version to version without notice, or even be removed. -// -// We mean it. -// - -#ifndef QGRAPHICSBSPTREEINDEX_H -#define QGRAPHICSBSPTREEINDEX_H - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Gui) - -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - -#include -#include -#include -#include -#include - -#include "qgraphicsscene_bsp_p.h" - -class QGraphicsSceneBspTreeIndexPrivate; - -class Q_AUTOTEST_EXPORT QGraphicsSceneBspTreeIndex : public QGraphicsSceneIndex -{ - Q_OBJECT - Q_PROPERTY(int bspTreeDepth READ bspTreeDepth WRITE setBspTreeDepth) -public: - QGraphicsSceneBspTreeIndex(QGraphicsScene *scene = 0); - QRectF indexedRect() const; - - QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const; - - QList items(Qt::SortOrder order = Qt::AscendingOrder) const; - - int bspTreeDepth(); - void setBspTreeDepth(int depth); - -protected: - bool event(QEvent *event); - void clear(); - - void addItem(QGraphicsItem *item); - void removeItem(QGraphicsItem *item); - void deleteItem(QGraphicsItem *item); - void prepareBoundingRectChange(const QGraphicsItem *item); - - void sceneRectChanged(const QRectF &rect); - void itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value); - -private : - Q_DECLARE_PRIVATE(QGraphicsSceneBspTreeIndex) - Q_DISABLE_COPY(QGraphicsSceneBspTreeIndex) - Q_PRIVATE_SLOT(d_func(), void _q_updateSortCache()) - Q_PRIVATE_SLOT(d_func(), void _q_updateIndex()) - - friend class QGraphicsScene; - friend class QGraphicsScenePrivate; -}; - -#endif // QT_NO_GRAPHICSVIEW - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QGRAPHICSBSPTREEINDEX_H diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h index ed12fac..1e4234e 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h @@ -39,8 +39,7 @@ ** ****************************************************************************/ -#ifndef QGRAPHICSSCENEBSPTREEINDEX_P_H -#define QGRAPHICSSCENEBSPTREEINDEX_P_H +#include // // W A R N I N G @@ -53,18 +52,66 @@ // We mean it. // -#include "qgraphicsscenebsptreeindex.h" +#ifndef QGRAPHICSBSPTREEINDEX_H +#define QGRAPHICSBSPTREEINDEX_H + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) #if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW -#include +#include +#include +#include +#include #include - -QT_BEGIN_NAMESPACE +#include +#include static const int QGRAPHICSSCENE_INDEXTIMER_TIMEOUT = 2000; class QGraphicsScene; +class QGraphicsSceneBspTreeIndexPrivate; + +class Q_AUTOTEST_EXPORT QGraphicsSceneBspTreeIndex : public QGraphicsSceneIndex +{ + Q_OBJECT + Q_PROPERTY(int bspTreeDepth READ bspTreeDepth WRITE setBspTreeDepth) +public: + QGraphicsSceneBspTreeIndex(QGraphicsScene *scene = 0); + QRectF indexedRect() const; + + QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const; + + QList items(Qt::SortOrder order = Qt::AscendingOrder) const; + + int bspTreeDepth(); + void setBspTreeDepth(int depth); + +protected: + bool event(QEvent *event); + void clear(); + + void addItem(QGraphicsItem *item); + void removeItem(QGraphicsItem *item); + void deleteItem(QGraphicsItem *item); + void prepareBoundingRectChange(const QGraphicsItem *item); + + void sceneRectChanged(const QRectF &rect); + void itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value); + +private : + Q_DECLARE_PRIVATE(QGraphicsSceneBspTreeIndex) + Q_DISABLE_COPY(QGraphicsSceneBspTreeIndex) + Q_PRIVATE_SLOT(d_func(), void _q_updateSortCache()) + Q_PRIVATE_SLOT(d_func(), void _q_updateIndex()) + + friend class QGraphicsScene; + friend class QGraphicsScenePrivate; +}; class QGraphicsSceneBspTreeIndexPrivate : public QGraphicsSceneIndexPrivate { @@ -183,9 +230,10 @@ static inline bool QRectF_intersects(const QRectF &s, const QRectF &r) return !(t1 >= b2 || t2 >= b1); } -QT_END_NAMESPACE +#endif // QT_NO_GRAPHICSVIEW -#endif // QGRAPHICSSCENEBSPTREEINDEX_P_H +QT_END_NAMESPACE -#endif +QT_END_HEADER +#endif // QGRAPHICSBSPTREEINDEX_H -- cgit v0.12 From 378b5b603bd269b631bbe108268a683adde11828 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Thu, 18 Jun 2009 15:02:05 +0200 Subject: Make the autotests compile again. Reviewed-by: Alexis --- .../tst_qgraphicssceneindex.cpp | 23 +++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp index 6b352ab..d10f86d 100644 --- a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp +++ b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp @@ -42,11 +42,10 @@ #include #include -#include #include +#include #include - //TESTED_CLASS= //TESTED_FILES= @@ -118,6 +117,7 @@ void tst_QGraphicsSceneIndex::customIndex_data() void tst_QGraphicsSceneIndex::customIndex() { +#if 0 QFETCH(QString, indexMethod); QGraphicsSceneIndex *index = createIndex(indexMethod); @@ -126,6 +126,7 @@ void tst_QGraphicsSceneIndex::customIndex() scene.addRect(0, 0, 30, 40); QCOMPARE(scene.items(QRectF(0, 0, 10, 10)).count(), 1); +#endif } void tst_QGraphicsSceneIndex::scatteredItems_data() @@ -136,10 +137,14 @@ void tst_QGraphicsSceneIndex::scatteredItems_data() void tst_QGraphicsSceneIndex::scatteredItems() { QFETCH(QString, indexMethod); - QGraphicsSceneIndex *index = createIndex(indexMethod); QGraphicsScene scene; +#if 1 + scene.setItemIndexMethod(indexMethod == "linear" ? QGraphicsScene::NoIndex : QGraphicsScene::BspTreeIndex); +#else + QGraphicsSceneIndex *index = createIndex(indexMethod); scene.setSceneIndex(index); +#endif for (int i = 0; i < 10; ++i) scene.addRect(i*50, i*50, 40, 35); @@ -161,10 +166,14 @@ void tst_QGraphicsSceneIndex::overlappedItems_data() void tst_QGraphicsSceneIndex::overlappedItems() { QFETCH(QString, indexMethod); - QGraphicsSceneIndex *index = createIndex(indexMethod); QGraphicsScene scene; +#if 1 + scene.setItemIndexMethod(indexMethod == "linear" ? QGraphicsScene::NoIndex : QGraphicsScene::BspTreeIndex); +#else + QGraphicsSceneIndex *index = createIndex(indexMethod); scene.setSceneIndex(index); +#endif for (int i = 0; i < 10; ++i) for (int j = 0; j < 10; ++j) @@ -191,10 +200,14 @@ void tst_QGraphicsSceneIndex::movingItems_data() void tst_QGraphicsSceneIndex::movingItems() { QFETCH(QString, indexMethod); - QGraphicsSceneIndex *index = createIndex(indexMethod); QGraphicsScene scene; +#if 1 + scene.setItemIndexMethod(indexMethod == "linear" ? QGraphicsScene::NoIndex : QGraphicsScene::BspTreeIndex); +#else + QGraphicsSceneIndex *index = createIndex(indexMethod); scene.setSceneIndex(index); +#endif for (int i = 0; i < 10; ++i) scene.addRect(i*50, i*50, 40, 35); -- cgit v0.12 From a18e5288324aa13da014ee52daffbfc589c87be3 Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Thu, 18 Jun 2009 17:29:42 +0200 Subject: Fix crash with untransformable items. Be sure that item goes in the correct list if it set its flags to untransformable. Reviewed-by: andreas --- .../graphicsview/qgraphicsscenebsptreeindex.cpp | 43 +++++++++++++++------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp index 27b5514..72636b8 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -548,14 +548,9 @@ void QGraphicsSceneBspTreeIndexPrivate::removeFromBspTree(QGraphicsItem *item) // ### remove from child index only if applicable return; } - int index = item->d_func()->index; - if (index != -1) { - bsp.removeItem(item, item->sceneBoundingRect()); - freeItemIndexes << index; - indexedItems[index] = 0; - item->d_func()->index = -1; - unindexedItems << item; + if (item->d_func()->index != -1) { + bsp.removeItem(item, item->sceneBoundingRect()); //prepareGeometryChange will call prepareBoundingRectChange foreach (QGraphicsItem *child, item->children()) child->prepareGeometryChange(); @@ -570,10 +565,20 @@ void QGraphicsSceneBspTreeIndexPrivate::removeFromBspTree(QGraphicsItem *item) void QGraphicsSceneBspTreeIndex::prepareBoundingRectChange(const QGraphicsItem *item) { Q_D(QGraphicsSceneBspTreeIndex); - // Note: This will access item's sceneBoundingRect(), which (as this is - // C++) is why we cannot call removeItem() from QGraphicsItem's - // destructor. - d->removeFromBspTree(const_cast(item)); + if (!item->d_ptr->itemIsUntransformable()) { + // Note: This will access item's sceneBoundingRect(), which (as this is + // C++) is why we cannot call removeItem() from QGraphicsItem's + // destructor. + QGraphicsItem *thatItem = const_cast(item); + d->removeFromBspTree(thatItem); + int index = item->d_func()->index; + if (index != -1) { + d->freeItemIndexes << index; + d->indexedItems[index] = 0; + thatItem->d_func()->index = -1; + d->unindexedItems << thatItem; + } + } } /*! @@ -725,7 +730,13 @@ void QGraphicsSceneBspTreeIndex::itemChange(const QGraphicsItem *item, QGraphics if (ignoredTransform != willIgnoreTransform) { QGraphicsItem *thatItem = const_cast(item); removeItem(thatItem); - addItem(thatItem); + thatItem->d_ptr->index = -1; + if (willIgnoreTransform) { + d->untransformableItems << thatItem; + } else { + d->unindexedItems << thatItem; + d->startIndexTimer(0); + } } break; } @@ -741,7 +752,13 @@ void QGraphicsSceneBspTreeIndex::itemChange(const QGraphicsItem *item, QGraphics if (ignoredTransform != willIgnoreTransform) { QGraphicsItem *thatItem = const_cast(item); removeItem(thatItem); - addItem(thatItem); + thatItem->d_ptr->index = -1; + if (willIgnoreTransform) { + d->untransformableItems << thatItem; + } else { + d->unindexedItems << thatItem; + d->startIndexTimer(0); + } } break; } -- cgit v0.12 From 8befd7589456c6fd193676daeba8f0779d88776e Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Mon, 22 Jun 2009 11:32:51 +0200 Subject: Remove unused code / delay in this autotest. --- tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index 1ca6c98..981efeb 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -4710,11 +4710,6 @@ void tst_QGraphicsItem::itemClipsChildrenToShape() scene.render(&painter); painter.end(); - QGraphicsView view(&scene); - view.show(); - - QTest::qWait(5000); - QCOMPARE(image.pixel(16, 16), QColor(255, 0, 0).rgba()); QCOMPARE(image.pixel(32, 32), QColor(0, 0, 255).rgba()); QCOMPARE(image.pixel(50, 50), QColor(0, 255, 0).rgba()); -- cgit v0.12 From 375c4f53e9702aa3273154c0879e3b6dbd2723d6 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Mon, 22 Jun 2009 11:38:17 +0200 Subject: QGraphicsSceneLinearIndex: touch-ups. --- src/gui/graphicsview/qgraphicsscenelinearindex_p.h | 39 +++++++++------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscenelinearindex_p.h b/src/gui/graphicsview/qgraphicsscenelinearindex_p.h index a5327ef..88e0e6a 100644 --- a/src/gui/graphicsview/qgraphicsscenelinearindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenelinearindex_p.h @@ -73,42 +73,35 @@ class Q_AUTOTEST_EXPORT QGraphicsSceneLinearIndex : public QGraphicsSceneIndex Q_OBJECT public: - QGraphicsSceneLinearIndex(QGraphicsScene *scene = 0): QGraphicsSceneIndex(scene) - { - } + QGraphicsSceneLinearIndex(QGraphicsScene *scene = 0) : QGraphicsSceneIndex(scene) + { } - QList items(Qt::SortOrder order = Qt::AscendingOrder) const { - Q_UNUSED(order); - return m_items; - } + QList items(Qt::SortOrder order = Qt::AscendingOrder) const + { Q_UNUSED(order); return m_items; } - virtual QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const { + virtual QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const + { Q_UNUSED(rect); Q_UNUSED(order); Q_UNUSED(deviceTransform); return m_items; } - virtual QRectF indexedRect() const { - return m_sceneRect; - } + virtual QRectF indexedRect() const + { return m_sceneRect; } protected : - void sceneRectChanged(const QRectF &rect) { - m_sceneRect = rect; - } + void sceneRectChanged(const QRectF &rect) + { m_sceneRect = rect; } - virtual void clear() { - m_items.clear(); - } + virtual void clear() + { m_items.clear(); } - virtual void addItem(QGraphicsItem *item) { - m_items << item; - } + virtual void addItem(QGraphicsItem *item) + { m_items << item; } - virtual void removeItem(QGraphicsItem *item) { - m_items.removeAll(item); - } + virtual void removeItem(QGraphicsItem *item) + { m_items.removeOne(item); } private: QRectF m_sceneRect; -- cgit v0.12 From be79229e9c454764d63262f46f686b3e1721ee2c Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Tue, 23 Jun 2009 12:35:31 +0200 Subject: More work on getting autotests to pass. --- src/gui/graphicsview/qgraphicsscene.cpp | 33 ++++++++++++++------ src/gui/graphicsview/qgraphicsscene_p.h | 1 + .../graphicsview/qgraphicsscenebsptreeindex.cpp | 36 +++++----------------- .../graphicsview/qgraphicsscenebsptreeindex_p.h | 3 +- src/gui/graphicsview/qgraphicssceneindex.cpp | 23 +++----------- src/gui/graphicsview/qgraphicssceneindex_p.h | 4 +-- src/gui/graphicsview/qgraphicsscenelinearindex_p.h | 7 ----- src/gui/graphicsview/qgraphicsview.cpp | 16 +++++----- tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp | 28 ++++++++++++++--- tests/auto/qgraphicsview/tst_qgraphicsview.cpp | 1 + 10 files changed, 71 insertions(+), 81 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 2f7ae04..6f92629 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -273,6 +273,7 @@ QGraphicsScenePrivate::QGraphicsScenePrivate() index(0), lastItemCount(0), hasSceneRect(false), + dirtyGrowingItemsBoundingRect(true), updateAll(false), calledEmitUpdated(false), processDirtyItemsEmitted(false), @@ -378,8 +379,9 @@ void QGraphicsScenePrivate::unregisterTopLevelItem(QGraphicsItem *item) */ void QGraphicsScenePrivate::_q_updateLater() { + QRectF null; foreach (QGraphicsItem *item, pendingUpdateItems) - item->update(); + markDirty(item, null); pendingUpdateItems.clear(); } @@ -409,8 +411,11 @@ void QGraphicsScenePrivate::_q_processDirtyItems() const bool wasPendingSceneUpdate = calledEmitUpdated; const QRectF oldGrowingItemsBoundingRect = growingItemsBoundingRect; processDirtyItemsRecursive(0); - if (!hasSceneRect && oldGrowingItemsBoundingRect != growingItemsBoundingRect) + dirtyGrowingItemsBoundingRect = false; + if (oldGrowingItemsBoundingRect != growingItemsBoundingRect) { + index->sceneRectChanged(); emit q_func()->sceneRectChanged(growingItemsBoundingRect); + } if (wasPendingSceneUpdate) return; @@ -1250,9 +1255,18 @@ QGraphicsScene::~QGraphicsScene() QRectF QGraphicsScene::sceneRect() const { Q_D(const QGraphicsScene); - /// ### Remove? The growing items bounding rect might be managed - // by the scene. - return d->index->indexedRect(); + if (!d->hasSceneRect && d->dirtyGrowingItemsBoundingRect) { + // Lazily update the growing items bounding rect + QGraphicsScenePrivate *thatd = const_cast(d); + QRectF oldGrowingBoundingRect = thatd->growingItemsBoundingRect; + thatd->growingItemsBoundingRect |= itemsBoundingRect(); + thatd->dirtyGrowingItemsBoundingRect = false; + if (oldGrowingBoundingRect != thatd->growingItemsBoundingRect) { + thatd->index->sceneRectChanged(); + emit const_cast(this)->sceneRectChanged(thatd->growingItemsBoundingRect); + } + } + return d->hasSceneRect ? d->sceneRect : d->growingItemsBoundingRect; } void QGraphicsScene::setSceneRect(const QRectF &rect) { @@ -1260,8 +1274,8 @@ void QGraphicsScene::setSceneRect(const QRectF &rect) if (rect != d->sceneRect) { d->hasSceneRect = !rect.isNull(); d->sceneRect = rect; - d->index->sceneRectChanged(rect); - emit sceneRectChanged(rect); + d->index->sceneRectChanged(); + emit sceneRectChanged(d->hasSceneRect ? rect : d->growingItemsBoundingRect); } } @@ -1411,8 +1425,6 @@ void QGraphicsScene::setItemIndexMethod(ItemIndexMethod method) d->index = new QGraphicsSceneLinearIndex(this); for (int i = oldItems.size() - 1; i >= 0; --i) d->index->addItem(oldItems.at(i)); - - d->index->sceneRectChanged(d->sceneRect); } /*! @@ -2057,6 +2069,8 @@ void QGraphicsScene::addItem(QGraphicsItem *item) if (d->pendingUpdateItems.isEmpty()) QMetaObject::invokeMethod(this, "_q_updateLater", Qt::QueuedConnection); d->pendingUpdateItems << item; + } else { + d->dirtyGrowingItemsBoundingRect = true; } // Disable selectionChanged() for individual items @@ -4235,6 +4249,7 @@ void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, b bool removingItemFromScene) { Q_ASSERT(item); + dirtyGrowingItemsBoundingRect = true; if (updateAll) return; diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index ea65707..8c4b2d2 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -95,6 +95,7 @@ public: QRectF sceneRect; bool hasSceneRect; + bool dirtyGrowingItemsBoundingRect; QRectF growingItemsBoundingRect; void _q_emitUpdated(); diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp index 72636b8..aeee982 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -122,7 +122,6 @@ void QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex() if (!indexTimerId) return; - QGraphicsScenePrivate * scenePrivate = q->scene()->d_func(); q->killTimer(indexTimerId); indexTimerId = 0; @@ -144,10 +143,6 @@ void QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex() } } - // Update growing scene rect. - QRectF oldGrowingItemsBoundingRect = scenePrivate->growingItemsBoundingRect; - scenePrivate->growingItemsBoundingRect |= unindexedItemsBoundingRect; - // Determine whether we should regenerate the BSP tree. if (bspTreeDepth == 0) { int oldDepth = intmaxlog(lastItemCount); @@ -165,7 +160,6 @@ void QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex() bsp.initialize(q->scene()->sceneRect(), bspTreeDepth); unindexedItems = indexedItems; lastItemCount = indexedItems.size(); - q->scene()->update(); } // Insert all unindexed items into the tree. @@ -179,10 +173,6 @@ void QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex() } } unindexedItems.clear(); - - // Notify scene rect changes. - if (!scenePrivate->hasSceneRect && scenePrivate->growingItemsBoundingRect != oldGrowingItemsBoundingRect) - emit q->scene()->sceneRectChanged(scenePrivate->growingItemsBoundingRect); } @@ -248,7 +238,7 @@ void QGraphicsSceneBspTreeIndexPrivate::climbTree(QGraphicsItem *item, int *stac { if (!item->d_ptr->children.isEmpty()) { QList childList = item->d_ptr->children; - qSort(childList.begin(), childList.end(), qt_closestLeaf); + qStableSort(childList.begin(), childList.end(), qt_closestLeaf); for (int i = 0; i < childList.size(); ++i) { QGraphicsItem *item = childList.at(i); if (!(item->flags() & QGraphicsItem::ItemStacksBehindParent)) @@ -287,7 +277,7 @@ void QGraphicsSceneBspTreeIndexPrivate::_q_updateSortCache() topLevels << item; } - qSort(topLevels.begin(), topLevels.end(), qt_closestLeaf); + qStableSort(topLevels.begin(), topLevels.end(), qt_closestLeaf); for (int i = 0; i < topLevels.size(); ++i) climbTree(topLevels.at(i), &stackingOrder); } @@ -379,15 +369,15 @@ void QGraphicsSceneBspTreeIndexPrivate::sortItems(QList *itemLi { if (sortCacheEnabled) { if (order == Qt::AscendingOrder) { - qSort(itemList->begin(), itemList->end(), closestItemFirst_withCache); + qStableSort(itemList->begin(), itemList->end(), closestItemFirst_withCache); } else if (order == Qt::DescendingOrder) { - qSort(itemList->begin(), itemList->end(), closestItemLast_withCache); + qStableSort(itemList->begin(), itemList->end(), closestItemLast_withCache); } } else { if (order == Qt::AscendingOrder) { - qSort(itemList->begin(), itemList->end(), closestItemFirst_withoutCache); + qStableSort(itemList->begin(), itemList->end(), closestItemFirst_withoutCache); } else if (order == Qt::DescendingOrder) { - qSort(itemList->begin(), itemList->end(), closestItemLast_withoutCache); + qStableSort(itemList->begin(), itemList->end(), closestItemLast_withoutCache); } } } @@ -403,17 +393,6 @@ QGraphicsSceneBspTreeIndex::QGraphicsSceneBspTreeIndex(QGraphicsScene *scene) /*! \reimp - Return the rect indexed by the BSP index. -*/ -QRectF QGraphicsSceneBspTreeIndex::indexedRect() const -{ - Q_D(const QGraphicsSceneBspTreeIndex); - const_cast(d)->_q_updateIndex(); - return scene()->d_func()->hasSceneRect ? scene()->d_func()->sceneRect : scene()->d_func()->growingItemsBoundingRect; -} - -/*! - \reimp Clear the all the BSP index. */ void QGraphicsSceneBspTreeIndex::clear() @@ -705,10 +684,9 @@ void QGraphicsSceneBspTreeIndex::setBspTreeDepth(int depth) This method react to the \a rect change of the scene and reset the BSP tree index. */ -void QGraphicsSceneBspTreeIndex::sceneRectChanged(const QRectF &rect) +void QGraphicsSceneBspTreeIndex::sceneRectChanged() { Q_D(QGraphicsSceneBspTreeIndex); - d->sceneRect = rect; d->resetIndex(); } diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h index 1e4234e..715b22f 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h @@ -82,7 +82,6 @@ class Q_AUTOTEST_EXPORT QGraphicsSceneBspTreeIndex : public QGraphicsSceneIndex Q_PROPERTY(int bspTreeDepth READ bspTreeDepth WRITE setBspTreeDepth) public: QGraphicsSceneBspTreeIndex(QGraphicsScene *scene = 0); - QRectF indexedRect() const; QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const; @@ -100,7 +99,7 @@ protected: void deleteItem(QGraphicsItem *item); void prepareBoundingRectChange(const QGraphicsItem *item); - void sceneRectChanged(const QRectF &rect); + void sceneRectChanged(); void itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value); private : diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index 8d7581f..4eaed2b 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -56,6 +56,7 @@ \sa QGraphicsScene, QGraphicsView */ +#include "qdebug.h" #include "qgraphicsscene.h" #include "qgraphicsitem_p.h" #include "qgraphicsscene_p.h" @@ -131,14 +132,10 @@ public: keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, pointPath, mode); } } else { - QRectF sceneBrect = transform.mapRect(brect); - keep = sceneBrect.contains(scenePoint); - if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) { - QPainterPath pointPath; - pointPath.addRect(QRectF(transform.inverted().map(scenePoint), QSizeF(1, 1))); - keep = QGraphicsSceneIndexPrivate::itemCollidesWithPath(item, pointPath, mode); - } + QRectF sceneBoundingRect = transform.mapRect(brect); + keep = sceneBoundingRect.intersects(QRectF(scenePoint, QSizeF(1, 1))) && item->contains(transform.inverted().map(scenePoint)); } + return keep; } @@ -366,15 +363,6 @@ QGraphicsScene* QGraphicsSceneIndex::scene() const } /*! - Returns the indexed area for the index -*/ -QRectF QGraphicsSceneIndex::indexedRect() const -{ - Q_D(const QGraphicsSceneIndex); - return d->scene->d_func()->sceneRect; -} - -/*! \fn QList QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform) const @@ -613,9 +601,8 @@ void QGraphicsSceneIndex::prepareBoundingRectChange(const QGraphicsItem *item) rectangle. \a rect is the new value of the scene rectangle. \sa QGraphicsScene::sceneRect() */ -void QGraphicsSceneIndex::sceneRectChanged(const QRectF &rect) +void QGraphicsSceneIndex::sceneRectChanged() { - Q_UNUSED(rect); } QT_END_NAMESPACE diff --git a/src/gui/graphicsview/qgraphicssceneindex_p.h b/src/gui/graphicsview/qgraphicssceneindex_p.h index 85a1140..60e9032 100644 --- a/src/gui/graphicsview/qgraphicssceneindex_p.h +++ b/src/gui/graphicsview/qgraphicssceneindex_p.h @@ -87,8 +87,6 @@ public: QGraphicsScene *scene() const; - virtual QRectF indexedRect() const; - virtual QList items(Qt::SortOrder order = Qt::AscendingOrder) const = 0; virtual QList items(const QPointF &pos, Qt::ItemSelectionMode mode, Qt::SortOrder order, const QTransform &deviceTransform = QTransform()) const; @@ -111,7 +109,7 @@ protected: virtual void itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange, const QVariant &value); virtual void prepareBoundingRectChange(const QGraphicsItem *item); - virtual void sceneRectChanged(const QRectF &rect); + virtual void sceneRectChanged(); QGraphicsSceneIndex(QObjectPrivate &dd, QGraphicsScene *scene); diff --git a/src/gui/graphicsview/qgraphicsscenelinearindex_p.h b/src/gui/graphicsview/qgraphicsscenelinearindex_p.h index 88e0e6a..9463487 100644 --- a/src/gui/graphicsview/qgraphicsscenelinearindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenelinearindex_p.h @@ -87,13 +87,7 @@ public: return m_items; } - virtual QRectF indexedRect() const - { return m_sceneRect; } - protected : - void sceneRectChanged(const QRectF &rect) - { m_sceneRect = rect; } - virtual void clear() { m_items.clear(); } @@ -104,7 +98,6 @@ protected : { m_items.removeOne(item); } private: - QRectF m_sceneRect; QList m_items; }; diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index ec1746a..640f85b 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -802,13 +802,15 @@ void QGraphicsViewPrivate::processPendingUpdates() return; } + if (optimizationFlags & QGraphicsView::DontAdjustForAntialiasing) + dirtyBoundingRect.adjust(-1, -1, 1, 1); + else + dirtyBoundingRect.adjust(-2, -2, 2, 2); + if (viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate) { - if (optimizationFlags & QGraphicsView::DontAdjustForAntialiasing) - viewport->update(dirtyBoundingRect.adjusted(-1, -1, 1, 1)); - else - viewport->update(dirtyBoundingRect.adjusted(-2, -2, 2, 2)); + viewport->update((dirtyRegion + dirtyBoundingRect).boundingRect()); } else { - viewport->update(dirtyRegion); // Already adjusted in updateRect/Region. + viewport->update(dirtyRegion + dirtyBoundingRect); // Already adjusted in updateRect/Region. } dirtyBoundingRect = QRect(); @@ -2087,9 +2089,7 @@ QGraphicsItem *QGraphicsView::itemAt(const QPoint &pos) const Q_D(const QGraphicsView); if (!d->scene) return 0; - // ### Use QGraphicsScene::itemAt() instead. - QList itemsAtPos = d->scene->items(pos, Qt::IntersectsItemShape, Qt::AscendingOrder, - viewportTransform()); + QList itemsAtPos = items(pos); return itemsAtPos.isEmpty() ? 0 : itemsAtPos.first(); } diff --git a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp index 1d03ef1..1a7a076 100644 --- a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp +++ b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp @@ -271,28 +271,46 @@ void tst_QGraphicsScene::construction() void tst_QGraphicsScene::sceneRect() { QGraphicsScene scene; + QSignalSpy sceneRectChanged(&scene, SIGNAL(sceneRectChanged(QRectF))); QCOMPARE(scene.sceneRect(), QRectF()); + QCOMPARE(sceneRectChanged.count(), 0); QGraphicsItem *item = scene.addRect(QRectF(0, 0, 10, 10)); - qApp->processEvents(); item->setPos(-5, -5); - qApp->processEvents(); + QCOMPARE(sceneRectChanged.count(), 0); QCOMPARE(scene.itemAt(0, 0), item); QCOMPARE(scene.itemAt(10, 10), (QGraphicsItem *)0); + QCOMPARE(sceneRectChanged.count(), 0); + QCOMPARE(scene.sceneRect(), QRectF(-5, -5, 10, 10)); + QCOMPARE(sceneRectChanged.count(), 1); + QCOMPARE(sceneRectChanged.last().at(0).toRectF(), scene.sceneRect()); + + item->setPos(0, 0); QCOMPARE(scene.sceneRect(), QRectF(-5, -5, 15, 15)); + QCOMPARE(sceneRectChanged.count(), 2); + QCOMPARE(sceneRectChanged.last().at(0).toRectF(), scene.sceneRect()); scene.setSceneRect(-100, -100, 10, 10); + QCOMPARE(sceneRectChanged.count(), 3); + QCOMPARE(sceneRectChanged.last().at(0).toRectF(), scene.sceneRect()); QCOMPARE(scene.itemAt(0, 0), item); QCOMPARE(scene.itemAt(10, 10), (QGraphicsItem *)0); QCOMPARE(scene.sceneRect(), QRectF(-100, -100, 10, 10)); + item->setPos(10, 10); + QCOMPARE(scene.sceneRect(), QRectF(-100, -100, 10, 10)); + QCOMPARE(sceneRectChanged.count(), 3); + QCOMPARE(sceneRectChanged.last().at(0).toRectF(), scene.sceneRect()); scene.setSceneRect(QRectF()); - QCOMPARE(scene.itemAt(0, 0), item); - QCOMPARE(scene.itemAt(10, 10), (QGraphicsItem *)0); - QCOMPARE(scene.sceneRect(), QRectF(-5, -5, 15, 15)); + QCOMPARE(scene.itemAt(10, 10), item); + QCOMPARE(scene.itemAt(20, 20), (QGraphicsItem *)0); + QCOMPARE(sceneRectChanged.count(), 4); + QCOMPARE(scene.sceneRect(), QRectF(-5, -5, 25, 25)); + QCOMPARE(sceneRectChanged.count(), 5); + QCOMPARE(sceneRectChanged.last().at(0).toRectF(), scene.sceneRect()); } void tst_QGraphicsScene::itemIndexMethod() diff --git a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp index c8c032a..02e4046 100644 --- a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp +++ b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp @@ -371,6 +371,7 @@ void tst_QGraphicsView::interactive() QCOMPARE(item->events.size(), 0); QPoint itemPoint = view.mapFromScene(item->scenePos()); + QVERIFY(view.itemAt(itemPoint)); for (int i = 0; i < 100; ++i) { -- cgit v0.12 From d39a62720ba67a0fa6e4e37519d22f14c7b7404e Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Tue, 23 Jun 2009 14:35:30 +0200 Subject: Ensure that the BSP index returns all untransformable items. --- src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp index aeee982..464fe8e 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -595,6 +595,8 @@ QList QGraphicsSceneBspTreeIndex::estimateItems(const QRectF &r for (int i = 0; i < rectItems.size(); ++i) rectItems.at(i)->d_func()->itemDiscovered = 0; + rectItems += d->untransformableItems; + d->sortItems(&rectItems, order, d->sortCacheEnabled); return rectItems; -- cgit v0.12 From b0f391ae8f2efc272be852f951403fa8e4a8f561 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Tue, 23 Jun 2009 16:57:32 +0200 Subject: Fix tst_QGraphicsItem::collidesWith_item autotest. Avoid unwanted recursion by keeping the sceneRect variable locally. The recursion happens if the call to sceneRect() lazily emits the sceneRectChanged() signal. --- src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp index 464fe8e..8861c7b 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -157,7 +157,7 @@ void QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex() // Regenerate the tree. if (regenerateIndex) { regenerateIndex = false; - bsp.initialize(q->scene()->sceneRect(), bspTreeDepth); + bsp.initialize(sceneRect, bspTreeDepth); unindexedItems = indexedItems; lastItemCount = indexedItems.size(); } @@ -689,6 +689,7 @@ void QGraphicsSceneBspTreeIndex::setBspTreeDepth(int depth) void QGraphicsSceneBspTreeIndex::sceneRectChanged() { Q_D(QGraphicsSceneBspTreeIndex); + d->sceneRect = d->scene->sceneRect(); d->resetIndex(); } -- cgit v0.12 From 4fb0f9d8d5275c21b3d16be1170b5e7d2ed77f8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 25 Jun 2009 14:36:03 +0200 Subject: Partially revert be79229e The change in processPendingUpdates was completely wrong and broke several auto-tests. --- src/gui/graphicsview/qgraphicsview.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 94547a5..e4decf9 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -802,15 +802,13 @@ void QGraphicsViewPrivate::processPendingUpdates() return; } - if (optimizationFlags & QGraphicsView::DontAdjustForAntialiasing) - dirtyBoundingRect.adjust(-1, -1, 1, 1); - else - dirtyBoundingRect.adjust(-2, -2, 2, 2); - if (viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate) { - viewport->update((dirtyRegion + dirtyBoundingRect).boundingRect()); + if (optimizationFlags & QGraphicsView::DontAdjustForAntialiasing) + viewport->update(dirtyBoundingRect.adjusted(-1, -1, 1, 1)); + else + viewport->update(dirtyBoundingRect.adjusted(-2, -2, 2, 2)); } else { - viewport->update(dirtyRegion + dirtyBoundingRect); // Already adjusted in updateRect/Region. + viewport->update(dirtyRegion); // Already adjusted in updateRect/Region. } dirtyBoundingRect = QRect(); -- cgit v0.12 From fe64e44b0dab0152101b4ec17a49305912415016 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 25 Jun 2009 14:42:16 +0200 Subject: Stabilize tst_QGraphicsView::moveItemWhileScrolling. --- tests/auto/qgraphicsview/tst_qgraphicsview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp index 02e4046..65e066f 100644 --- a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp +++ b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp @@ -3093,7 +3093,7 @@ void tst_QGraphicsView::moveItemWhileScrolling() #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&view); #endif - QTest::qWait(100); + QTest::qWait(200); view.lastPaintedRegion = QRegion(); view.horizontalScrollBar()->setValue(view.horizontalScrollBar()->value() + 10); -- cgit v0.12 From 93e3a72f56d4b9ab020c58a2a3fac79be5fe49eb Mon Sep 17 00:00:00 2001 From: David Boddie Date: Thu, 25 Jun 2009 16:15:01 +0200 Subject: Doc: Indicated that QCompleter::completionModel() returns a proxy model. Task-number: 256138 Reviewed-by: jasplin --- src/gui/util/qcompleter.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gui/util/qcompleter.cpp b/src/gui/util/qcompleter.cpp index 3d25f13..f4adcea 100644 --- a/src/gui/util/qcompleter.cpp +++ b/src/gui/util/qcompleter.cpp @@ -1582,6 +1582,10 @@ QString QCompleter::currentCompletion() const that contains all the possible matches for the current completion prefix. The completion model is auto-updated to reflect the current completions. + \note The return value of this function is defined to be an QAbstractItemModel + purely for generality. This actual kind of model returned is an instance of an + QAbstractProxyModel subclass. + \sa completionPrefix, model() */ QAbstractItemModel *QCompleter::completionModel() const -- cgit v0.12 From 9dc1fc2d30205bb0bad12df4d3cb061f55f4f3f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 25 Jun 2009 16:42:10 +0200 Subject: Compile tst_QGrahicsSceneIndex after be79229e --- .../auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp index d10f86d..ac21e20 100644 --- a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp +++ b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp @@ -56,8 +56,6 @@ public slots: void initTestCase(); private slots: - void sceneRect_data(); - void sceneRect(); void customIndex_data(); void customIndex(); void scatteredItems_data(); @@ -97,19 +95,6 @@ QGraphicsSceneIndex *tst_QGraphicsSceneIndex::createIndex(const QString &indexMe return index; } -void tst_QGraphicsSceneIndex::sceneRect_data() -{ - common_data(); -} - -void tst_QGraphicsSceneIndex::sceneRect() -{ - QGraphicsScene *scene = new QGraphicsScene(); - QGraphicsSceneIndex *index = new QGraphicsSceneBspTreeIndex(scene); - scene->setSceneRect(QRectF(0, 0, 2000, 2000)); - QCOMPARE(index->indexedRect(), QRectF(0, 0, 2000, 2000)); -} - void tst_QGraphicsSceneIndex::customIndex_data() { common_data(); -- cgit v0.12 From eab949e2ec8f820a54826c1a837c8c8de07814ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 25 Jun 2009 11:31:04 +0200 Subject: Re-factor parts of the QGraphicsSceneBspTreeIndex. This patch adds better support for untransformable items and removes some redundant code. --- src/gui/graphicsview/qgraphicsscene.cpp | 22 +- .../graphicsview/qgraphicsscenebsptreeindex.cpp | 282 +++++++++------------ .../graphicsview/qgraphicsscenebsptreeindex_p.h | 6 +- 3 files changed, 133 insertions(+), 177 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 06a251e..6efede2 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -1954,25 +1954,13 @@ void QGraphicsScene::clearSelection() void QGraphicsScene::clear() { Q_D(QGraphicsScene); - QList items = d->index->items(); -#if 1 - QList toDelete; - // ### As the item list is already in ascending order, - // the items should be deleted in topological order. - // Recursive descent delete - for (int i = 0; i < items.size(); ++i) { - if (QGraphicsItem *item = items.at(i)) { - if (!item->parentItem()) - toDelete << item; - } - } - // We delete all top level items - qDeleteAll(toDelete); -#else + // NB! We have to clear the index before deleting items; otherwise the + // index might try to access dangling item pointers. + d->index->clear(); + const QList items = d->topLevelItems; qDeleteAll(items); -#endif + Q_ASSERT(d->topLevelItems.isEmpty()); d->lastItemCount = 0; - d->index->clear(); d->allItemsIgnoreHoverEvents = true; d->allItemsUseDefaultCursor = true; } diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp index 8861c7b..f6994f9 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -128,10 +128,9 @@ void QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex() purgeRemovedItems(); // Add unindexedItems to indexedItems - QRectF unindexedItemsBoundingRect; for (int i = 0; i < unindexedItems.size(); ++i) { if (QGraphicsItem *item = unindexedItems.at(i)) { - unindexedItemsBoundingRect |= item->sceneBoundingRect(); + item->d_ptr->itemDiscovered = 0; if (!freeItemIndexes.isEmpty()) { int freeIndex = freeItemIndexes.takeFirst(); item->d_func()->index = freeIndex; @@ -165,11 +164,14 @@ void QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex() // Insert all unindexed items into the tree. for (int i = 0; i < unindexedItems.size(); ++i) { if (QGraphicsItem *item = unindexedItems.at(i)) { - QRectF rect = item->sceneBoundingRect(); + if (item->d_ptr->itemIsUntransformable()) { + untransformableItems << item; + continue; + } if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) continue; - bsp.insertItem(item, rect); + bsp.insertItem(item, item->sceneBoundingRect()); } } unindexedItems.clear(); @@ -222,11 +224,13 @@ void QGraphicsSceneBspTreeIndexPrivate::resetIndex() for (int i = 0; i < indexedItems.size(); ++i) { if (QGraphicsItem *item = indexedItems.at(i)) { item->d_ptr->index = -1; + item->d_ptr->itemDiscovered = 0; unindexedItems << item; } } indexedItems.clear(); freeItemIndexes.clear(); + untransformableItems.clear(); regenerateIndex = true; startIndexTimer(); } @@ -270,10 +274,10 @@ void QGraphicsSceneBspTreeIndexPrivate::_q_updateSortCache() int stackingOrder = 0; QList topLevels; - - for (int i = 0; i < q->items().count(); ++i) { - QGraphicsItem *item = q->items().at(i); - if (item && item->parentItem() == 0) + const QList items = q->items(); + for (int i = 0; i < items.size(); ++i) { + QGraphicsItem *item = items.at(i); + if (item && !item->d_ptr->parent) topLevels << item; } @@ -295,6 +299,79 @@ void QGraphicsSceneBspTreeIndexPrivate::invalidateSortCache() QMetaObject::invokeMethod(q, "_q_updateSortCache", Qt::QueuedConnection); } +void QGraphicsSceneBspTreeIndexPrivate::addItem(QGraphicsItem *item, bool recursive) +{ + if (!item) + return; + + // Prevent reusing a recently deleted pointer: purge all removed item from our lists. + purgeRemovedItems(); + + // Invalidate any sort caching; arrival of a new item means we need to resort. + // Update the scene's sort cache settings. + item->d_ptr->globalStackingOrder = -1; + invalidateSortCache(); + + // Indexing requires sceneBoundingRect(), but because \a item might + // not be completely constructed at this point, we need to store it in + // a temporary list and schedule an indexing for later. + if (item->d_ptr->index == -1) { + Q_ASSERT(!unindexedItems.contains(item)); + unindexedItems << item; + startIndexTimer(0); + } else { + Q_ASSERT(indexedItems.contains(item)); + qWarning("QGraphicsSceneBspTreeIndex::addItem: item has already been added to this BSP"); + } + + if (recursive) { + for (int i = 0; i < item->d_ptr->children.size(); ++i) + addItem(item->d_ptr->children.at(i), recursive); + } +} + +void QGraphicsSceneBspTreeIndexPrivate::removeItem(QGraphicsItem *item, bool recursive, + bool moveToUnindexedItems) +{ + if (!item) + return; + + if (item->d_ptr->index != -1) { + Q_ASSERT(item->d_ptr->index < indexedItems.size()); + Q_ASSERT(indexedItems.at(item->d_ptr->index) == item); + freeItemIndexes << item->d_ptr->index; + indexedItems[item->d_ptr->index] = 0; + item->d_ptr->index = -1; + item->d_ptr->itemDiscovered = 0; + + if (item->d_ptr->itemIsUntransformable()) { + untransformableItems.removeOne(item); + } else if (item->d_ptr->inDestructor) { + // Avoid virtual function calls from the destructor. + purgePending = true; + removedItems << item; + } else if (!item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) { + bsp.removeItem(item, item->sceneBoundingRect()); + } + } else { + unindexedItems.removeOne(item); + } + invalidateSortCache(); // ### Only do this when removing from BSP? + + Q_ASSERT(item->d_ptr->index == -1); + Q_ASSERT(!indexedItems.contains(item)); + Q_ASSERT(!unindexedItems.contains(item)); + Q_ASSERT(!untransformableItems.contains(item)); + + if (moveToUnindexedItems) + addItem(item); + + if (recursive) { + for (int i = 0; i < item->d_ptr->children.size(); ++i) + removeItem(item->d_ptr->children.at(i), recursive, moveToUnindexedItems); + } +} + /*! Returns true if \a item1 is on top of \a item2. @@ -401,8 +478,16 @@ void QGraphicsSceneBspTreeIndex::clear() d->bsp.clear(); d->lastItemCount = 0; d->freeItemIndexes.clear(); + for (int i = 0; i < d->indexedItems.size(); ++i) { + // Ensure item bits are reset properly. + if (QGraphicsItem *item = d->indexedItems.at(i)) { + item->d_ptr->index = -1; + item->d_ptr->itemDiscovered = 0; + } + } d->indexedItems.clear(); d->unindexedItems.clear(); + d->untransformableItems.clear(); } /*! @@ -411,46 +496,7 @@ void QGraphicsSceneBspTreeIndex::clear() void QGraphicsSceneBspTreeIndex::addItem(QGraphicsItem *item) { Q_D(QGraphicsSceneBspTreeIndex); - // Prevent reusing a recently deleted pointer: purge all removed items - // from our lists. - d->purgeRemovedItems(); - - // Invalidate any sort caching; arrival of a new item means we need to - // resort. - // Update the scene's sort cache settings. - item->d_ptr->globalStackingOrder = -1; - d->invalidateSortCache(); - - // Indexing requires sceneBoundingRect(), but because \a item might - // not be completely constructed at this point, we need to store it in - // a temporary list and schedule an indexing for later. - item->d_ptr->index = -1; - if (item->d_ptr->itemIsUntransformable()) { - d->untransformableItems << item; - } else { - d->unindexedItems << item; - d->startIndexTimer(0); - } -} - -/*! - This really add the item in the BSP. - \internal -*/ -void QGraphicsSceneBspTreeIndexPrivate::addToBspTree(QGraphicsItem *item) -{ - if (item->d_ptr->itemIsUntransformable()) - return; - if (item->d_func()->index != -1) { - bsp.insertItem(item, item->sceneBoundingRect()); - foreach (QGraphicsItem *child, item->children()) - child->addToIndex(); - } else { - // The BSP tree is regenerated if the number of items grows to a - // certain threshold, or if the bounding rect of the graph doubles in - // size. - startIndexTimer(); - } + d->addItem(item); } /*! @@ -459,105 +505,28 @@ void QGraphicsSceneBspTreeIndexPrivate::addToBspTree(QGraphicsItem *item) void QGraphicsSceneBspTreeIndex::removeItem(QGraphicsItem *item) { Q_D(QGraphicsSceneBspTreeIndex); - - // Note: This will access item's sceneBoundingRect(), which (as this is - // C++) is why we cannot call removeItem() from QGraphicsItem's - // destructor. - d->removeFromBspTree(item); - - // Invalidate any sort caching; arrival of a new item means we need to - // resort. - d->invalidateSortCache(); - - // Remove from our item lists. - int index = item->d_func()->index; - if (index != -1) { - d->freeItemIndexes << index; - d->indexedItems[index] = 0; - } else { - if (item->d_ptr->itemIsUntransformable()) - d->untransformableItems.removeOne(item); - else - d->unindexedItems.removeOne(item); - } + d->removeItem(item); } /*! \reimp - Delete the \a item from the BSP index (without accessing its boundingRect). -*/ -void QGraphicsSceneBspTreeIndex::deleteItem(QGraphicsItem *item) -{ - Q_D(QGraphicsSceneBspTreeIndex); - // Invalidate any sort caching; arrival of a new item means we need to - // resort. - d->invalidateSortCache(); - - int index = item->d_func()->index; - if (index != -1) { - // Important: The index is useless until purgeRemovedItems() is - // called. - d->indexedItems[index] = (QGraphicsItem *)0; - if (!d->purgePending) { - d->purgePending = true; - scene()->update(); - } - d->removedItems << item; - } else { - // Recently added items are purged immediately. unindexedItems() never - // contains stale items. - if (item->d_ptr->itemIsUntransformable()) - d->untransformableItems.removeOne(item); - else - d->unindexedItems.removeOne(item); - scene()->update(); - } -} - -/*! - Really remove the item from the BSP - \internal + Update the BSP when the \a item 's bounding rect has changed. */ -void QGraphicsSceneBspTreeIndexPrivate::removeFromBspTree(QGraphicsItem *item) +void QGraphicsSceneBspTreeIndex::prepareBoundingRectChange(const QGraphicsItem *item) { - if (item->d_ptr->itemIsUntransformable()) + if (!item) return; - if (item->d_func()->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) { - // ### remove from child index only if applicable - return; + if (item->d_ptr->index == -1 || item->d_ptr->itemIsUntransformable() + || item->d_func()->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) { + return; // Item is not in BSP tree; nothing to do. } - if (item->d_func()->index != -1) { - bsp.removeItem(item, item->sceneBoundingRect()); - //prepareGeometryChange will call prepareBoundingRectChange - foreach (QGraphicsItem *child, item->children()) - child->prepareGeometryChange(); - } - startIndexTimer(); -} - -/*! - \reimp - Update the BSP when the \a item 's bounding rect has changed. -*/ -void QGraphicsSceneBspTreeIndex::prepareBoundingRectChange(const QGraphicsItem *item) -{ Q_D(QGraphicsSceneBspTreeIndex); - if (!item->d_ptr->itemIsUntransformable()) { - // Note: This will access item's sceneBoundingRect(), which (as this is - // C++) is why we cannot call removeItem() from QGraphicsItem's - // destructor. - QGraphicsItem *thatItem = const_cast(item); - d->removeFromBspTree(thatItem); - int index = item->d_func()->index; - if (index != -1) { - d->freeItemIndexes << index; - d->indexedItems[index] = 0; - thatItem->d_func()->index = -1; - d->unindexedItems << thatItem; - } - } + QGraphicsItem *thatItem = const_cast(item); + d->removeItem(thatItem, /*recursive=*/false, /*moveToUnindexedItems=*/true); + for (int i = 0; i < item->d_ptr->children.size(); ++i) // ### Do we really need this? + prepareBoundingRectChange(item->d_ptr->children.at(i)); } /*! @@ -706,18 +675,17 @@ void QGraphicsSceneBspTreeIndex::itemChange(const QGraphicsItem *item, QGraphics switch (change) { case QGraphicsItem::ItemFlagsChange: { // Handle ItemIgnoresTransformations - bool ignoredTransform = item->flags() & QGraphicsItem::ItemIgnoresTransformations; + bool ignoredTransform = item->d_ptr->flags & QGraphicsItem::ItemIgnoresTransformations; bool willIgnoreTransform = value.toUInt() & QGraphicsItem::ItemIgnoresTransformations; - if (ignoredTransform != willIgnoreTransform) { + bool clipsChildren = item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape; + bool willClipChildren = value.toUInt() & QGraphicsItem::ItemClipsChildrenToShape; + if ((ignoredTransform != willIgnoreTransform) || (clipsChildren != willClipChildren)) { QGraphicsItem *thatItem = const_cast(item); - removeItem(thatItem); - thatItem->d_ptr->index = -1; - if (willIgnoreTransform) { - d->untransformableItems << thatItem; - } else { - d->unindexedItems << thatItem; - d->startIndexTimer(0); - } + // Remove item and its descendants from the index and append + // them to the list of unindexed items. Then, when the index + // is updated, they will be put into the bsp-tree or the list + // of untransformable items. + d->removeItem(thatItem, /*recursive=*/true, /*moveToUnidexedItems=*/true); } break; } @@ -729,17 +697,19 @@ void QGraphicsSceneBspTreeIndex::itemChange(const QGraphicsItem *item, QGraphics // Handle ItemIgnoresTransformations QGraphicsItem *newParent = qVariantValue(value); bool ignoredTransform = item->d_ptr->itemIsUntransformable(); - bool willIgnoreTransform = (item->flags() & QGraphicsItem::ItemIgnoresTransformations) || (newParent && newParent->d_ptr->itemIsUntransformable()); - if (ignoredTransform != willIgnoreTransform) { + bool willIgnoreTransform = (item->d_ptr->flags & QGraphicsItem::ItemIgnoresTransformations) + || (newParent && newParent->d_ptr->itemIsUntransformable()); + bool ancestorClippedChildren = item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren; + bool ancestorWillClipChildren = newParent + && ((newParent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape) + || (newParent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)); + if ((ignoredTransform != willIgnoreTransform) || (ancestorClippedChildren != ancestorWillClipChildren)) { QGraphicsItem *thatItem = const_cast(item); - removeItem(thatItem); - thatItem->d_ptr->index = -1; - if (willIgnoreTransform) { - d->untransformableItems << thatItem; - } else { - d->unindexedItems << thatItem; - d->startIndexTimer(0); - } + // Remove item and its descendants from the index and append + // them to the list of unindexed items. Then, when the index + // is updated, they will be put into the bsp-tree or the list + // of untransformable items. + d->removeItem(thatItem, /*recursive=*/true, /*moveToUnidexedItems=*/true); } break; } diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h index 715b22f..f2f958f 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h @@ -96,7 +96,6 @@ protected: void addItem(QGraphicsItem *item); void removeItem(QGraphicsItem *item); - void deleteItem(QGraphicsItem *item); void prepareBoundingRectChange(const QGraphicsItem *item); void sceneRectChanged(); @@ -139,13 +138,12 @@ public: void startIndexTimer(int interval = QGRAPHICSSCENE_INDEXTIMER_TIMEOUT); void resetIndex(); - void addToBspTree(QGraphicsItem *item); - void removeFromBspTree(QGraphicsItem *item); - void _q_updateSortCache(); bool sortCacheEnabled; bool updatingSortCache; void invalidateSortCache(); + void addItem(QGraphicsItem *item, bool recursive = false); + void removeItem(QGraphicsItem *item, bool recursive = false, bool moveToUnindexedItems = false); static void climbTree(QGraphicsItem *item, int *stackingOrder); static bool closestItemFirst_withoutCache(const QGraphicsItem *item1, const QGraphicsItem *item2); -- cgit v0.12 From 7541247a025bf112716a752bc4d114303f2a77f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Fri, 26 Jun 2009 15:54:04 +0200 Subject: Proper handling of scene rect in QGraphicsScene(Index). Reviewed-by: Andreas --- src/gui/graphicsview/qgraphicsitem.cpp | 1 + src/gui/graphicsview/qgraphicsitem_p.h | 2 +- src/gui/graphicsview/qgraphicsscene.cpp | 65 +++++++++------------- src/gui/graphicsview/qgraphicsscene.h | 1 - src/gui/graphicsview/qgraphicsscene_p.h | 1 - .../graphicsview/qgraphicsscenebsptreeindex.cpp | 4 +- .../graphicsview/qgraphicsscenebsptreeindex_p.h | 4 +- src/gui/graphicsview/qgraphicssceneindex.cpp | 25 ++++++--- src/gui/graphicsview/qgraphicssceneindex_p.h | 4 +- src/gui/graphicsview/qgraphicsscenelinearindex.cpp | 6 -- 10 files changed, 52 insertions(+), 61 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 7393f00..e9d1076 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -6322,6 +6322,7 @@ void QGraphicsItem::removeFromIndex() void QGraphicsItem::prepareGeometryChange() { if (d_ptr->scene) { + d_ptr->scene->d_func()->dirtyGrowingItemsBoundingRect = true; d_ptr->geometryChanged = 1; d_ptr->paintedViewBoundingRectsNeedRepaint = 1; diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 1dfb140..243582a 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -148,7 +148,7 @@ public: dirtyChildrenBoundingRect(1), paintedViewBoundingRectsNeedRepaint(0), dirtySceneTransform(1), - geometryChanged(0), + geometryChanged(1), inDestructor(0), isObject(0), ignoreVisible(0), diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 6efede2..de6f5c4 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -326,6 +326,16 @@ void QGraphicsScenePrivate::_q_emitUpdated() Q_Q(QGraphicsScene); calledEmitUpdated = false; + if (dirtyGrowingItemsBoundingRect) { + if (!hasSceneRect) { + const QRectF oldGrowingItemsBoundingRect = growingItemsBoundingRect; + growingItemsBoundingRect |= q->itemsBoundingRect(); + if (oldGrowingItemsBoundingRect != growingItemsBoundingRect) + emit q->sceneRectChanged(growingItemsBoundingRect); + } + dirtyGrowingItemsBoundingRect = false; + } + // Ensure all views are connected if anything is connected. This disables // the optimization that items send updates directly to the views, but it // needs to happen in order to keep compatibility with the behavior from @@ -373,20 +383,6 @@ void QGraphicsScenePrivate::unregisterTopLevelItem(QGraphicsItem *item) /*! \internal - - Updates all items in the pending update list. At this point, the list is - unlikely to contain partially constructed items. -*/ -void QGraphicsScenePrivate::_q_updateLater() -{ - QRectF null; - foreach (QGraphicsItem *item, pendingUpdateItems) - markDirty(item, null); - pendingUpdateItems.clear(); -} - -/*! - \internal */ void QGraphicsScenePrivate::_q_polishItems() { @@ -412,10 +408,8 @@ void QGraphicsScenePrivate::_q_processDirtyItems() const QRectF oldGrowingItemsBoundingRect = growingItemsBoundingRect; processDirtyItemsRecursive(0); dirtyGrowingItemsBoundingRect = false; - if (oldGrowingItemsBoundingRect != growingItemsBoundingRect) { - index->sceneRectChanged(); + if (!hasSceneRect && oldGrowingItemsBoundingRect != growingItemsBoundingRect) emit q_func()->sceneRectChanged(growingItemsBoundingRect); - } if (wasPendingSceneUpdate) return; @@ -507,7 +501,6 @@ void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item) hoverItems.removeAll(item); cachedItemsUnderMouse.removeAll(item); unpolishedItems.removeAll(item); - pendingUpdateItems.removeAll(item); resetDirtyItem(item); //We remove all references of item from the sceneEventFilter arrays @@ -1303,18 +1296,19 @@ QGraphicsScene::~QGraphicsScene() QRectF QGraphicsScene::sceneRect() const { Q_D(const QGraphicsScene); - if (!d->hasSceneRect && d->dirtyGrowingItemsBoundingRect) { + if (d->hasSceneRect) + return d->sceneRect; + + if (d->dirtyGrowingItemsBoundingRect) { // Lazily update the growing items bounding rect QGraphicsScenePrivate *thatd = const_cast(d); QRectF oldGrowingBoundingRect = thatd->growingItemsBoundingRect; thatd->growingItemsBoundingRect |= itemsBoundingRect(); thatd->dirtyGrowingItemsBoundingRect = false; - if (oldGrowingBoundingRect != thatd->growingItemsBoundingRect) { - thatd->index->sceneRectChanged(); + if (oldGrowingBoundingRect != thatd->growingItemsBoundingRect) emit const_cast(this)->sceneRectChanged(thatd->growingItemsBoundingRect); - } } - return d->hasSceneRect ? d->sceneRect : d->growingItemsBoundingRect; + return d->growingItemsBoundingRect; } void QGraphicsScene::setSceneRect(const QRectF &rect) { @@ -1322,7 +1316,6 @@ void QGraphicsScene::setSceneRect(const QRectF &rect) if (rect != d->sceneRect) { d->hasSceneRect = !rect.isNull(); d->sceneRect = rect; - d->index->sceneRectChanged(); emit sceneRectChanged(d->hasSceneRect ? rect : d->growingItemsBoundingRect); } } @@ -2101,13 +2094,8 @@ void QGraphicsScene::addItem(QGraphicsItem *item) // Add to list of items that require an update. We cannot assume that the // item is fully constructed, so calling item->update() can lead to a pure // virtual function call to boundingRect(). - if (!d->updateAll) { - if (d->pendingUpdateItems.isEmpty()) - QMetaObject::invokeMethod(this, "_q_updateLater", Qt::QueuedConnection); - d->pendingUpdateItems << item; - } else { - d->dirtyGrowingItemsBoundingRect = true; - } + d->markDirty(item); + d->dirtyGrowingItemsBoundingRect = true; // Disable selectionChanged() for individual items ++d->selectionChanging; @@ -4245,7 +4233,6 @@ void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, b bool removingItemFromScene) { Q_ASSERT(item); - dirtyGrowingItemsBoundingRect = true; if (updateAll) return; @@ -4351,6 +4338,13 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool item->d_ptr->dirty = 0; item->d_ptr->paintedViewBoundingRectsNeedRepaint = 0; } + + if (item->d_ptr->geometryChanged) { + // Update growingItemsBoundingRect. + if (!hasSceneRect && !itemIsHidden) + growingItemsBoundingRect |= item->d_ptr->sceneTransform.mapRect(item->boundingRect()); + item->d_ptr->geometryChanged = 0; + } } // Process item. @@ -4359,13 +4353,6 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool const bool untransformableItem = item->d_ptr->itemIsUntransformable(); const QRectF itemBoundingRect = adjustedItemBoundingRect(item); - if (item->d_ptr->geometryChanged) { - // Update growingItemsBoundingRect. - if (!hasSceneRect) - growingItemsBoundingRect |= item->d_ptr->sceneTransform.mapRect(itemBoundingRect); - item->d_ptr->geometryChanged = 0; - } - if (useCompatUpdate && !untransformableItem && qFuzzyIsNull(item->boundingRegionGranularity())) { // This block of code is kept for compatibility. Since 4.5, by default // QGraphicsView does not connect the signal and we use the below diff --git a/src/gui/graphicsview/qgraphicsscene.h b/src/gui/graphicsview/qgraphicsscene.h index 421adbd..560671a 100644 --- a/src/gui/graphicsview/qgraphicsscene.h +++ b/src/gui/graphicsview/qgraphicsscene.h @@ -291,7 +291,6 @@ private: Q_DECLARE_PRIVATE(QGraphicsScene) Q_DISABLE_COPY(QGraphicsScene) Q_PRIVATE_SLOT(d_func(), void _q_emitUpdated()) - Q_PRIVATE_SLOT(d_func(), void _q_updateLater()) Q_PRIVATE_SLOT(d_func(), void _q_polishItems()) Q_PRIVATE_SLOT(d_func(), void _q_processDirtyItems()) friend class QGraphicsItem; diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 36a7e63..f286a8d 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -107,7 +107,6 @@ public: QPainterPath selectionArea; int selectionChanging; QSet selectedItems; - QList pendingUpdateItems; QList unpolishedItems; QList topLevelItems; bool needSortTopLevelItems; diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp index f6994f9..3efc742 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -655,10 +655,10 @@ void QGraphicsSceneBspTreeIndex::setBspTreeDepth(int depth) This method react to the \a rect change of the scene and reset the BSP tree index. */ -void QGraphicsSceneBspTreeIndex::sceneRectChanged() +void QGraphicsSceneBspTreeIndex::updateSceneRect(const QRectF &rect) { Q_D(QGraphicsSceneBspTreeIndex); - d->sceneRect = d->scene->sceneRect(); + d->sceneRect = rect; d->resetIndex(); } diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h index f2f958f..850cc3f 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h @@ -90,6 +90,9 @@ public: int bspTreeDepth(); void setBspTreeDepth(int depth); +protected Q_SLOTS: + void updateSceneRect(const QRectF &rect); + protected: bool event(QEvent *event); void clear(); @@ -98,7 +101,6 @@ protected: void removeItem(QGraphicsItem *item); void prepareBoundingRectChange(const QGraphicsItem *item); - void sceneRectChanged(); void itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange change, const QVariant &value); private : diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index 4eaed2b..88fb6b0 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -335,6 +335,10 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRe QGraphicsSceneIndex::QGraphicsSceneIndex(QGraphicsScene *scene) : QObject(*new QGraphicsSceneIndexPrivate(scene), scene) { + if (scene) { + connect(scene, SIGNAL(sceneRectChanged(const QRectF&)), + this, SLOT(updateSceneRect(const QRectF&))); + } } /*! @@ -527,6 +531,18 @@ QList QGraphicsSceneIndex::estimateItems(const QPointF &point, \a order. */ + +/*! + Notifies the index that the scene's scene rect has changed. \a rect + is thew new scene rect. + + \sa QGraphicsScene::sceneRect() +*/ +void QGraphicsSceneIndex::updateSceneRect(const QRectF &rect) +{ + Q_UNUSED(rect); +} + /*! This virtual function removes all items in the scene index. */ @@ -596,15 +612,6 @@ void QGraphicsSceneIndex::prepareBoundingRectChange(const QGraphicsItem *item) Q_UNUSED(item); } -/*! - This virtual function is called when the scene changes its bounding - rectangle. \a rect is the new value of the scene rectangle. - \sa QGraphicsScene::sceneRect() -*/ -void QGraphicsSceneIndex::sceneRectChanged() -{ -} - QT_END_NAMESPACE #include "moc_qgraphicssceneindex_p.cpp" diff --git a/src/gui/graphicsview/qgraphicssceneindex_p.h b/src/gui/graphicsview/qgraphicssceneindex_p.h index 60e9032..dc6a740 100644 --- a/src/gui/graphicsview/qgraphicssceneindex_p.h +++ b/src/gui/graphicsview/qgraphicssceneindex_p.h @@ -101,6 +101,9 @@ public: virtual QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const = 0; +protected Q_SLOTS: + virtual void updateSceneRect(const QRectF &rect); + protected: virtual void clear(); virtual void addItem(QGraphicsItem *item) = 0; @@ -109,7 +112,6 @@ protected: virtual void itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange, const QVariant &value); virtual void prepareBoundingRectChange(const QGraphicsItem *item); - virtual void sceneRectChanged(); QGraphicsSceneIndex(QObjectPrivate &dd, QGraphicsScene *scene); diff --git a/src/gui/graphicsview/qgraphicsscenelinearindex.cpp b/src/gui/graphicsview/qgraphicsscenelinearindex.cpp index 694062b..bc401f2 100644 --- a/src/gui/graphicsview/qgraphicsscenelinearindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenelinearindex.cpp @@ -46,12 +46,6 @@ */ /*! - \fn void QGraphicsSceneLinearIndex::sceneRectChanged(const QRectF &rect); - \reimp - This method react to the \a rect change of the scene. -*/ - -/*! \fn void QGraphicsSceneLinearIndex::clear(); \reimp Clear the all the BSP index. -- cgit v0.12 From eff4c4b4172d1a95b1b5806622b4e7fe43c2b006 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Fri, 26 Jun 2009 16:32:27 +0200 Subject: Fix broken point item lookup in Graphics View. Done with Andreas. --- src/gui/graphicsview/qgraphicsscene.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index de6f5c4..7c46598 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -770,11 +770,22 @@ QList QGraphicsScenePrivate::itemsAtPosition(const QPoint &scre const QPointF &scenePos, QWidget *widget) const { - Q_UNUSED(screenPos); Q_Q(const QGraphicsScene); QGraphicsView *view = widget ? qobject_cast(widget->parentWidget()) : 0; - return q->items(scenePos, Qt::IntersectsItemShape, Qt::AscendingOrder, - view ? view->viewportTransform() : QTransform()); + if (!view) + return q->items(scenePos, Qt::IntersectsItemShape, Qt::AscendingOrder, QTransform()); + + const QRectF pointRect(QPointF(widget->mapFromGlobal(screenPos)), QSizeF(1, 1)); + if (!view->isTransformed()) + return q->items(pointRect, Qt::IntersectsItemShape, Qt::AscendingOrder); + + const QTransform viewTransform = view->viewportTransform(); + if (viewTransform.type() <= QTransform::TxScale) { + return q->items(viewTransform.inverted().mapRect(pointRect), Qt::IntersectsItemShape, + Qt::AscendingOrder, viewTransform); + } + return q->items(viewTransform.inverted().map(pointRect), Qt::IntersectsItemShape, + Qt::AscendingOrder, viewTransform); } /*! -- cgit v0.12 From 7fe4f8ff71cf09bbabbd3438ef637fe408a11c33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Mon, 29 Jun 2009 15:33:30 +0200 Subject: Graphics View: BSP tree cleanup. Ensure the BSP resets the QGraphicsItemPrivate::itemDiscovered bit before returning the list of discovered items. --- src/gui/graphicsview/qgraphicsitem.h | 1 + src/gui/graphicsview/qgraphicsscene.cpp | 7 +++++-- src/gui/graphicsview/qgraphicsscene_bsp.cpp | 11 ++++++++--- src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp | 21 ++++++++------------- 4 files changed, 22 insertions(+), 18 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index 12dcad2..48fb5c3 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -434,6 +434,7 @@ private: friend class QGraphicsScene; friend class QGraphicsScenePrivate; friend class QGraphicsSceneFindItemBspTreeVisitor; + friend class QGraphicsSceneBspTree; friend class QGraphicsView; friend class QGraphicsViewPrivate; friend class QGraphicsWidget; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 7c46598..f1e56c1 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -1097,8 +1097,11 @@ QList QGraphicsScenePrivate::topLevelItemsInStackingOrder(const QList tmp = index->estimateItems(sceneRect, Qt::SortOrder(-1), viewTransform ? *viewTransform : QTransform()); - for (int i = 0; i < tmp.size(); ++i) - tmp.at(i)->topLevelItem()->d_ptr->itemDiscovered = 1; + for (int i = 0; i < tmp.size(); ++i) { + QGraphicsItem *item = tmp.at(i); + if (!item->d_ptr->parent) + item->d_ptr->itemDiscovered = 1; + } // Sort if the toplevel list is unsorted. if (needSortTopLevelItems) { diff --git a/src/gui/graphicsview/qgraphicsscene_bsp.cpp b/src/gui/graphicsview/qgraphicsscene_bsp.cpp index eaeec54..5858eab 100644 --- a/src/gui/graphicsview/qgraphicsscene_bsp.cpp +++ b/src/gui/graphicsview/qgraphicsscene_bsp.cpp @@ -148,6 +148,9 @@ QList QGraphicsSceneBspTree::items(const QRectF &rect) const QList tmp; findVisitor->foundItems = &tmp; climbTree(findVisitor, rect); + // Reset discovery bits. + for (int i = 0; i < tmp.size(); ++i) + tmp.at(i)->d_ptr->itemDiscovered = 0; return tmp; } @@ -156,6 +159,9 @@ QList QGraphicsSceneBspTree::items(const QPointF &pos) const QList tmp; findVisitor->foundItems = &tmp; climbTree(findVisitor, pos); + // Reset discovery bits. + for (int i = 0; i < tmp.size(); ++i) + tmp.at(i)->d_ptr->itemDiscovered = 0; return tmp; } @@ -241,7 +247,7 @@ void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, con return; const Node &node = nodes.at(index); - int childIndex = firstChildIndex(index); + const int childIndex = firstChildIndex(index); switch (node.type) { case Node::Leaf: { @@ -271,7 +277,7 @@ void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, con return; const Node &node = nodes.at(index); - int childIndex = firstChildIndex(index); + const int childIndex = firstChildIndex(index); switch (node.type) { case Node::Leaf: { @@ -288,7 +294,6 @@ void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, con } break; case Node::Horizontal: - int childIndex = firstChildIndex(index); if (rect.top() < node.offset) { climbTree(visitor, rect, childIndex); if (rect.bottom() >= node.offset) diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp index 3efc742..44a0082 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -130,7 +130,7 @@ void QGraphicsSceneBspTreeIndexPrivate::_q_updateIndex() // Add unindexedItems to indexedItems for (int i = 0; i < unindexedItems.size(); ++i) { if (QGraphicsItem *item = unindexedItems.at(i)) { - item->d_ptr->itemDiscovered = 0; + Q_ASSERT(!item->d_ptr->itemDiscovered); if (!freeItemIndexes.isEmpty()) { int freeIndex = freeItemIndexes.takeFirst(); item->d_func()->index = freeIndex; @@ -224,7 +224,7 @@ void QGraphicsSceneBspTreeIndexPrivate::resetIndex() for (int i = 0; i < indexedItems.size(); ++i) { if (QGraphicsItem *item = indexedItems.at(i)) { item->d_ptr->index = -1; - item->d_ptr->itemDiscovered = 0; + Q_ASSERT(!item->d_ptr->itemDiscovered); unindexedItems << item; } } @@ -339,10 +339,10 @@ void QGraphicsSceneBspTreeIndexPrivate::removeItem(QGraphicsItem *item, bool rec if (item->d_ptr->index != -1) { Q_ASSERT(item->d_ptr->index < indexedItems.size()); Q_ASSERT(indexedItems.at(item->d_ptr->index) == item); + Q_ASSERT(!item->d_ptr->itemDiscovered); freeItemIndexes << item->d_ptr->index; indexedItems[item->d_ptr->index] = 0; item->d_ptr->index = -1; - item->d_ptr->itemDiscovered = 0; if (item->d_ptr->itemIsUntransformable()) { untransformableItems.removeOne(item); @@ -481,8 +481,8 @@ void QGraphicsSceneBspTreeIndex::clear() for (int i = 0; i < d->indexedItems.size(); ++i) { // Ensure item bits are reset properly. if (QGraphicsItem *item = d->indexedItems.at(i)) { + Q_ASSERT(!item->d_ptr->itemDiscovered); item->d_ptr->index = -1; - item->d_ptr->itemDiscovered = 0; } } d->indexedItems.clear(); @@ -547,25 +547,20 @@ QList QGraphicsSceneBspTreeIndex::estimateItems(const QRectF &r Q_UNUSED(deviceTransform); QList rectItems = d->bsp.items(rect); + // Fill in with any unindexed items for (int i = 0; i < d->unindexedItems.size(); ++i) { if (QGraphicsItem *item = d->unindexedItems.at(i)) { - if (!item->d_ptr->itemDiscovered && item->d_ptr->visible && !(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) { + if (item->d_ptr->visible + && !(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) { QRectF boundingRect = item->sceneBoundingRect(); - if (QRectF_intersects(boundingRect, rect)) { - item->d_ptr->itemDiscovered = 1; + if (QRectF_intersects(boundingRect, rect)) rectItems << item; - } } } } - // Reset the discovered state of all discovered items - for (int i = 0; i < rectItems.size(); ++i) - rectItems.at(i)->d_func()->itemDiscovered = 0; - rectItems += d->untransformableItems; - d->sortItems(&rectItems, order, d->sortCacheEnabled); return rectItems; -- cgit v0.12 From 4dcb46a3796fbd9baf1ba6dcddcc9944e69e3153 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Mon, 29 Jun 2009 15:44:11 +0200 Subject: Add lacking parenthesis around bitwise AND operator. This caused a crash in the diagramscene example because "!bits & something" does not have the same meaning as "!(bits & something)", hence item was never removed from the BSP resulting in a stale item pointer. --- src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp index 44a0082..413c8de 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -350,7 +350,7 @@ void QGraphicsSceneBspTreeIndexPrivate::removeItem(QGraphicsItem *item, bool rec // Avoid virtual function calls from the destructor. purgePending = true; removedItems << item; - } else if (!item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) { + } else if (!(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) { bsp.removeItem(item, item->sceneBoundingRect()); } } else { @@ -518,7 +518,7 @@ void QGraphicsSceneBspTreeIndex::prepareBoundingRectChange(const QGraphicsItem * return; if (item->d_ptr->index == -1 || item->d_ptr->itemIsUntransformable() - || item->d_func()->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) { + || (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) { return; // Item is not in BSP tree; nothing to do. } -- cgit v0.12 From 5c23c8e36d07410e53026c7ddd19f00f9984a6e7 Mon Sep 17 00:00:00 2001 From: Bill King Date: Tue, 30 Jun 2009 13:39:58 +1000 Subject: Fixes more DB autotests for testing against SQL Server --- tests/auto/q3sqlcursor/tst_q3sqlcursor.cpp | 1 + tests/auto/qsqldatabase/tst_databases.h | 59 +++++++++++++++++++--------- tests/auto/qsqldatabase/tst_qsqldatabase.cpp | 4 +- 3 files changed, 44 insertions(+), 20 deletions(-) diff --git a/tests/auto/q3sqlcursor/tst_q3sqlcursor.cpp b/tests/auto/q3sqlcursor/tst_q3sqlcursor.cpp index 2d89639..fa786f1 100644 --- a/tests/auto/q3sqlcursor/tst_q3sqlcursor.cpp +++ b/tests/auto/q3sqlcursor/tst_q3sqlcursor.cpp @@ -135,6 +135,7 @@ void tst_Q3SqlCursor::createTestTables( QSqlDatabase db ) if (tst_Databases::isSqlServer(db)) { QVERIFY_SQL(q, exec("SET ANSI_DEFAULTS ON")); + QVERIFY_SQL(q, exec("SET IMPLICIT_TRANSACTIONS OFF")); } // please never ever change this table; otherwise fix all tests ;) diff --git a/tests/auto/qsqldatabase/tst_databases.h b/tests/auto/qsqldatabase/tst_databases.h index b81182a..c6b65a4 100644 --- a/tests/auto/qsqldatabase/tst_databases.h +++ b/tests/auto/qsqldatabase/tst_databases.h @@ -217,7 +217,7 @@ public: // addDb( "QMYSQL3", "testdb", "troll", "trond", "horsehead.nokia.troll.no", 3309, "CLIENT_COMPRESS=1;CLIENT_SSL=1" ); // MySQL 5.0.18 Linux // addDb( "QMYSQL3", "testdb", "troll", "trond", "iceblink.nokia.troll.no" ); // MySQL 5.0.13 Windows // addDb( "QMYSQL3", "testdb", "testuser", "Ee4Gabf6_", "mysql4-nokia.trolltech.com.au" ); // MySQL 4.1.22-2.el4 linux -// addDb( "QMYSQL3", "testdb", "testuser", "Ee4Gabf6_", "mysql5-nokia.trolltech.com.au" ); // MySQL 5.0.45-7.el5 linux +// addDb( "QMYSQL3", "testdb", "testuser", "Ee4Gabf6_", "mysql5-nokia.trolltech.com.au" ); // MySQL 5.0.45-7.el5 linux // addDb( "QPSQL7", "testdb", "troll", "trond", "horsehead.nokia.troll.no" ); // V7.2 NOT SUPPORTED! // addDb( "QPSQL7", "testdb", "troll", "trond", "horsehead.nokia.troll.no", 5434 ); // V7.2 NOT SUPPORTED! Multi-byte @@ -239,7 +239,7 @@ public: // use in-memory database to prevent local files // addDb("QSQLITE", ":memory:"); - addDb( "QSQLITE", QDir::toNativeSeparators(QDir::tempPath()+"/foo.db") ); + addDb( "QSQLITE", QDir::toNativeSeparators(QDir::tempPath()+"/foo.db") ); // addDb( "QSQLITE2", QDir::toNativeSeparators(QDir::tempPath()+"/foo2.db") ); // addDb( "QODBC3", "DRIVER={SQL SERVER};SERVER=iceblink.nokia.troll.no\\ICEBLINK", "troll", "trond", "" ); // addDb( "QODBC3", "DRIVER={SQL Native Client};SERVER=silence.nokia.troll.no\\SQLEXPRESS", "troll", "trond", "" ); @@ -251,6 +251,8 @@ public: // addDb( "QODBC", "DRIVER={FreeTDS};SERVER=bq-winserv2008-x86-01.apac.nokia.com;DATABASE=testdb;PORT=1433;UID=testuser;PWD=Ee4Gabf6_;TDS_Version=8.0", "testuser", "Ee4Gabf6_", "" ); // addDb( "QTDS7", "testdb", "testuser", "Ee4Gabf6_", "bq-winserv2003" ); // addDb( "QTDS7", "testdb", "testuser", "Ee4Gabf6_", "bq-winserv2008" ); +// addDb( "QODBC3", "DRIVER={SQL SERVER};SERVER=bq-winserv2003-x86-01.apac.nokia.com;DATABASE=testdb;PORT=1433", "testuser", "Ee4Gabf6_", "" ); +// addDb( "QODBC3", "DRIVER={SQL SERVER};SERVER=bq-winserv2008-x86-01.apac.nokia.com;DATABASE=testdb;PORT=1433", "testuser", "Ee4Gabf6_", "" ); } void open() @@ -316,20 +318,28 @@ public: QSqlQuery q( db ); QStringList dbtables=db.tables(); - foreach(QString tableName, tableNames) + foreach(const QString &tableName, tableNames) { wasDropped = true; QString table=tableName; if ( db.driver()->isIdentifierEscaped(table, QSqlDriver::TableName)) table = db.driver()->stripDelimiters(table, QSqlDriver::TableName); - if ( dbtables.contains( table, Qt::CaseSensitive ) ) - wasDropped = q.exec( "drop table " + tableName); - else if ( dbtables.contains( table, Qt::CaseInsensitive ) ) - wasDropped = q.exec( "drop table " + tableName); - - if ( !wasDropped ) - qWarning() << dbToString(db) << "unable to drop table" << tableName << ':' << q.lastError().text() << "tables:" << dbtables; + if ( dbtables.contains( table, Qt::CaseInsensitive ) ) { + foreach(const QString &table2, dbtables.filter(table, Qt::CaseInsensitive)) { + if(table2.compare(table.section('.', -1, -1), Qt::CaseInsensitive) == 0) { + table=db.driver()->escapeIdentifier(table2, QSqlDriver::TableName); + wasDropped = q.exec( "drop table " + table); + dbtables.removeAll(table); + } + } + } + if ( !wasDropped ) { + qWarning() << dbToString(db) << "unable to drop table" << tableName << ':' << q.lastError(); +// qWarning() << "last query:" << q.lastQuery(); +// qWarning() << "dbtables:" << dbtables; +// qWarning() << "db.tables():" << db.tables(); + } } } @@ -343,19 +353,32 @@ public: if ( isMSAccess( db ) ) // Access is sooo stupid. safeDropTables( db, viewNames ); + bool wasDropped; + QSqlQuery q( db ); QStringList dbtables=db.tables(QSql::Views); foreach(QString viewName, viewNames) { - if ( dbtables.contains( viewName, Qt::CaseInsensitive ) ) { - QSqlQuery q( "drop view " + viewName, db ); - - if ( !q.isActive() ) - qWarning() << "unable to drop view" << viewName << ':' << q.lastError().text(); - } else if ( db.driverName().startsWith( "QMYSQL" ) - && dbtables.contains( viewName, Qt::CaseInsensitive ) ) { // MySql is a bit stupid too - QSqlQuery q( "drop view " + viewName, db ); + wasDropped = true; + QString view=viewName; + if ( db.driver()->isIdentifierEscaped(view, QSqlDriver::TableName)) + view = db.driver()->stripDelimiters(view, QSqlDriver::TableName); + + if ( dbtables.contains( view, Qt::CaseInsensitive ) ) { + foreach(const QString &view2, dbtables.filter(view, Qt::CaseInsensitive)) { + if(view2.compare(view.section('.', -1, -1), Qt::CaseInsensitive) == 0) { + view=db.driver()->escapeIdentifier(view2, QSqlDriver::TableName); + wasDropped = q.exec( "drop view " + view); + dbtables.removeAll(view); + } + } } + + if ( !wasDropped ) + qWarning() << dbToString(db) << "unable to drop view" << viewName << ':' << q.lastError(); +// << "\nlast query:" << q.lastQuery() +// << "\ndbtables:" << dbtables +// << "\ndb.tables(QSql::Views):" << db.tables(QSql::Views); } } diff --git a/tests/auto/qsqldatabase/tst_qsqldatabase.cpp b/tests/auto/qsqldatabase/tst_qsqldatabase.cpp index f697488..23b1eb5 100644 --- a/tests/auto/qsqldatabase/tst_qsqldatabase.cpp +++ b/tests/auto/qsqldatabase/tst_qsqldatabase.cpp @@ -298,6 +298,7 @@ void tst_QSqlDatabase::createTestTables(QSqlDatabase db) q.exec("set table_type=innodb"); if (tst_Databases::isSqlServer(db)) { QVERIFY_SQL(q, exec("SET ANSI_DEFAULTS ON")); + QVERIFY_SQL(q, exec("SET IMPLICIT_TRANSACTIONS OFF")); } // please never ever change this table; otherwise fix all tests ;) @@ -354,10 +355,9 @@ void tst_QSqlDatabase::dropTestTables(QSqlDatabase db) q.exec("drop schema " + qTableName("qtestschema") + " cascade"); if (testWhiteSpaceNames(db.driverName())) - tableNames << (qTableName("qtest") + " test"); + tableNames << db.driver()->escapeIdentifier(qTableName("qtest") + " test", QSqlDriver::TableName); tst_Databases::safeDropTables(db, tableNames); - tst_Databases::safeDropView(db, qTableName("qtest_view")); } void tst_QSqlDatabase::populateTestTables(QSqlDatabase db) -- cgit v0.12 From 06303a608cd45395fde897f97e58cbfaadc32366 Mon Sep 17 00:00:00 2001 From: Ritt Konstantin Date: Tue, 30 Jun 2009 09:21:46 +0200 Subject: fix column-spanning in Designer ConnectDialog's layout if showAllCheckBox's text is longer than 1/2 of dialog's width then dialog became asymmetric. Reviewed-by: Friedemann Kleint --- tools/designer/src/components/signalsloteditor/connectdialog.ui | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/designer/src/components/signalsloteditor/connectdialog.ui b/tools/designer/src/components/signalsloteditor/connectdialog.ui index bd062eb..568516a 100644 --- a/tools/designer/src/components/signalsloteditor/connectdialog.ui +++ b/tools/designer/src/components/signalsloteditor/connectdialog.ui @@ -13,7 +13,7 @@ Configure Connection - + GroupBox @@ -53,7 +53,7 @@ - + GroupBox @@ -93,14 +93,14 @@ - + Show signals and slots inherited from QWidget - + Qt::Horizontal -- cgit v0.12 From aa5def2013cb362ddcb8cd4233f37ef936fe0302 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Tue, 30 Jun 2009 10:59:22 +0200 Subject: Fixed QLayout to take the maxi/min size into account for the menu bar It was only taking the sizeHint into account Task-number: 141355 Reviewed-by: jasplin --- src/gui/kernel/qlayout.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/gui/kernel/qlayout.cpp b/src/gui/kernel/qlayout.cpp index 3a3feb2..e750088 100644 --- a/src/gui/kernel/qlayout.cpp +++ b/src/gui/kernel/qlayout.cpp @@ -61,7 +61,10 @@ static int menuBarHeightForWidth(QWidget *menubar, int w) int result = menubar->heightForWidth(qMax(w, menubar->minimumWidth())); if (result != -1) return result; - result = menubar->sizeHint().height(); + result = menubar->sizeHint() + .expandedTo(menubar->minimumSize()) + .expandedTo(menubar->minimumSizeHint()) + .boundedTo(menubar->maximumSize()).height(); if (result != -1) return result; } -- cgit v0.12 From 0a4930f7e0d324d9ec75e4fe8775b8acf21b4ce1 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Tue, 30 Jun 2009 11:05:44 +0200 Subject: QMenu: fixed a crash when clicking on a menu with a submenu --- src/gui/widgets/qmenu.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gui/widgets/qmenu.cpp b/src/gui/widgets/qmenu.cpp index 56b8cb1..31df3f6 100644 --- a/src/gui/widgets/qmenu.cpp +++ b/src/gui/widgets/qmenu.cpp @@ -483,9 +483,9 @@ void QMenuPrivate::setSyncAction() void QMenuPrivate::setFirstActionActive() { Q_Q(QMenu); + updateActionRects(); const int scrollerHeight = q->style()->pixelMetric(QStyle::PM_MenuScrollerHeight, 0, q); for(int i = 0, saccum = 0; i < actions.count(); i++) { - QAction *act = actions.at(i); const QRect &rect = actionRects.at(i); if (rect.isNull()) continue; @@ -494,6 +494,7 @@ void QMenuPrivate::setFirstActionActive() if (saccum > scroll->scrollOffset-scrollerHeight) continue; } + QAction *act = actions.at(i); if (!act->isSeparator() && (q->style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, 0, q) || act->isEnabled())) { -- cgit v0.12 From 225aa3154d3c9940775254ed261d6dd8b9123c62 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Tue, 30 Jun 2009 11:13:24 +0200 Subject: QMenu: when we access the actions geometry, it's now always up2date --- src/gui/widgets/qmenu.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/gui/widgets/qmenu.cpp b/src/gui/widgets/qmenu.cpp index 31df3f6..d3f5bc5 100644 --- a/src/gui/widgets/qmenu.cpp +++ b/src/gui/widgets/qmenu.cpp @@ -667,6 +667,7 @@ void QMenuPrivate::scrollMenu(QAction *action, QMenuScroller::ScrollLocation loc Q_Q(QMenu); if (!scroll || !scroll->scrollFlags) return; + updateActionRects(); int newOffset = 0; const int scrollHeight = q->style()->pixelMetric(QStyle::PM_MenuScrollerHeight, 0, q); const int topScroll = (scroll->scrollFlags & QMenuScroller::ScrollUp) ? scrollHeight : 0; @@ -769,6 +770,7 @@ void QMenuPrivate::scrollMenu(QAction *action, QMenuScroller::ScrollLocation loc void QMenuPrivate::scrollMenu(QMenuScroller::ScrollLocation location, bool active) { Q_Q(QMenu); + updateActionRects(); if(location == QMenuScroller::ScrollBottom) { for(int i = actions.size()-1; i >= 0; --i) { QAction *act = actions.at(i); @@ -808,6 +810,7 @@ void QMenuPrivate::scrollMenu(QMenuScroller::ScrollDirection direction, bool pag Q_Q(QMenu); if (!scroll || !(scroll->scrollFlags & direction)) //not really possible... return; + updateActionRects(); const int scrollHeight = q->style()->pixelMetric(QStyle::PM_MenuScrollerHeight, 0, q); const int topScroll = (scroll->scrollFlags & QMenuScroller::ScrollUp) ? scrollHeight : 0; const int botScroll = (scroll->scrollFlags & QMenuScroller::ScrollDown) ? scrollHeight : 0; @@ -2059,6 +2062,7 @@ void QMenu::hideEvent(QHideEvent *) void QMenu::paintEvent(QPaintEvent *e) { Q_D(QMenu); + d->updateActionRects(); QPainter p(this); QRegion emptyArea = QRegion(rect()); @@ -2345,6 +2349,7 @@ bool QMenu::focusNextPrevChild(bool next) void QMenu::keyPressEvent(QKeyEvent *e) { Q_D(QMenu); + d->updateActionRects(); int key = e->key(); if (isRightToLeft()) { // in reverse mode open/close key for submenues are reversed if (key == Qt::Key_Left) -- cgit v0.12 From a823334a1b61f7a8cf73d96cbc4cd0f71bdc3df7 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Tue, 30 Jun 2009 11:20:20 +0200 Subject: QMenuBar: make sure to update the geometries when needed --- src/gui/widgets/qmenubar.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gui/widgets/qmenubar.cpp b/src/gui/widgets/qmenubar.cpp index 7982d98..f4288ac 100644 --- a/src/gui/widgets/qmenubar.cpp +++ b/src/gui/widgets/qmenubar.cpp @@ -279,6 +279,7 @@ QRect QMenuBarPrivate::actionRect(QAction *act) const void QMenuBarPrivate::focusFirstAction() { if(!currentAction) { + updateGeometries(); int index = 0; while (index < actions.count() && actionRects.at(index).isNull()) ++index; if (index < actions.count()) @@ -757,6 +758,7 @@ void QMenuBarPrivate::init() QAction *QMenuBarPrivate::getNextAction(const int _start, const int increment) const { Q_Q(const QMenuBar); + const_cast(this)->updateGeometries(); bool allowActiveAndDisabled = q->style()->styleHint(QStyle::SH_Menu_AllowActiveAndDisabled, 0, q); const int start = (_start == -1 && increment == -1) ? actions.count() : _start; const int end = increment == -1 ? 0 : actions.count() - 1; @@ -1123,6 +1125,7 @@ void QMenuBar::mouseReleaseEvent(QMouseEvent *e) void QMenuBar::keyPressEvent(QKeyEvent *e) { Q_D(QMenuBar); + d->updateGeometries(); int key = e->key(); if(isRightToLeft()) { // in reverse mode open/close key for submenues are reversed if(key == Qt::Key_Left) @@ -1597,6 +1600,7 @@ QSize QMenuBar::minimumSizeHint() const ensurePolished(); QSize ret(0, 0); + const_cast(d)->updateGeometries(); const int hmargin = style()->pixelMetric(QStyle::PM_MenuBarHMargin, 0, this); const int vmargin = style()->pixelMetric(QStyle::PM_MenuBarVMargin, 0, this); int fw = style()->pixelMetric(QStyle::PM_MenuBarPanelWidth, 0, this); -- cgit v0.12 From 5a54b2c4c448ea22adb56bc191303abca34f230b Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Tue, 30 Jun 2009 12:11:32 +0200 Subject: qdoc: Added more handling of \reimp command Also fixed a few qdoc error reports. Task-number: 162182, 222650 --- src/gui/kernel/qevent.cpp | 33 +++++++++++++++++++++---------- tools/qdoc3/cppcodeparser.cpp | 3 ++- tools/qdoc3/generator.cpp | 42 +++++++++++++++++++++++----------------- tools/qdoc3/generator.h | 4 ++-- tools/qdoc3/javadocgenerator.cpp | 3 ++- tools/qdoc3/javadocgenerator.h | 2 +- tools/qdoc3/node.cpp | 12 ++++++++++++ tools/qdoc3/node.h | 4 ++++ 8 files changed, 70 insertions(+), 33 deletions(-) diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 2467a62..e40ad9d 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -3647,12 +3647,13 @@ void QGestureEvent::acceptAll() } /*! - Sets the accept flag of the specified gesture inside the event - object, the equivalent of calling - \l{QGestureEvent::gesture()}{gesture(type)}->\l{QGesture::accept()}{accept()} + Sets the accept flag of the gesture specified by \a type. + This is equivalent to calling + \l{QGestureEvent::gesture()}{gesture(type)}-> + \l{QGesture::accept()}{accept()} - Setting the accept parameter indicates that the event receiver - wants the gesture. Unwanted gestures might be propagated to the parent + Setting the accept flag indicates that the event receiver wants + the gesture. Unwanted gestures might be propagated to the parent widget. */ void QGestureEvent::accept(Qt::GestureType type) @@ -3662,12 +3663,13 @@ void QGestureEvent::accept(Qt::GestureType type) } /*! - Sets the accept flag of the specified gesture inside the event - object, the equivalent of calling - \l{QGestureEvent::gesture()}{gesture(type)}->\l{QGesture::accept()}{accept()} + Sets the accept flag of the gesture specified by \a type. + This is equivalent to calling + \l{QGestureEvent::gesture()}{gesture(type)}-> + \l{QGesture::accept()}{accept()} - Setting the accept parameter indicates that the event receiver - wants the gesture. Unwanted gestures might be propagated to the parent + Setting the accept flag indicates that the event receiver wants + the gesture. Unwanted gestures might be propagated to the parent widget. */ void QGestureEvent::accept(const QString &type) @@ -4165,4 +4167,15 @@ QTouchEvent::TouchPoint &QTouchEvent::TouchPoint::operator=(const QTouchEvent::T return *this; } +/*! \fn QTouchEvent::DeviceType QTouchEvent::deviceType() const + Returns the touch device Type, which is of type + \l {QTouchEvent::DeviceType} {DeviceType}. + */ + +/*! \fn void QTouchEvent::setDeviceType(DeviceType deviceType) + Sets the device type to \a deviceType, which is of type + \l {QTouchEvent::DeviceType} {DeviceType}. + */ + + QT_END_NAMESPACE diff --git a/tools/qdoc3/cppcodeparser.cpp b/tools/qdoc3/cppcodeparser.cpp index 792190d..cb6caa9 100644 --- a/tools/qdoc3/cppcodeparser.cpp +++ b/tools/qdoc3/cppcodeparser.cpp @@ -743,7 +743,8 @@ void CppCodeParser::processOtherMetaCommand(const Doc& doc, // Reimplemented functions now reported in separate sections. func->setAccess(Node::Private); func->setStatus(Node::Internal); -#endif +#endif + func->setReimp(true); } else { doc.location().warning(tr("Ignored '\\%1' in %2") diff --git a/tools/qdoc3/generator.cpp b/tools/qdoc3/generator.cpp index fa55b8a..7e10f3e 100644 --- a/tools/qdoc3/generator.cpp +++ b/tools/qdoc3/generator.cpp @@ -241,7 +241,7 @@ void Generator::generateFakeNode(const FakeNode * /* fake */, { } -void Generator::generateText(const Text& text, +bool Generator::generateText(const Text& text, const Node *relative, CodeMarker *marker) { @@ -254,31 +254,35 @@ void Generator::generateText(const Text& text, true, numAtoms); endText(relative, marker); + return true; } + return false; } #ifdef QDOC_QML -void Generator::generateQmlText(const Text& text, +bool Generator::generateQmlText(const Text& text, const Node *relative, CodeMarker *marker) { - if (text.firstAtom() != 0) { - startText(relative, marker); - const Atom *atom = text.firstAtom(); - while (atom) { - if (atom->type() != Atom::QmlText) - atom = atom->next(); - else { - atom = atom->next(); - while (atom && (atom->type() != Atom::EndQmlText)) { - int n = 1 + generateAtom(atom, relative, marker); - while (n-- > 0) - atom = atom->next(); - } + const Atom* atom = text.firstAtom(); + if (atom == 0) + return false; + + startText(relative, marker); + while (atom) { + if (atom->type() != Atom::QmlText) + atom = atom->next(); + else { + atom = atom->next(); + while (atom && (atom->type() != Atom::EndQmlText)) { + int n = 1 + generateAtom(atom, relative, marker); + while (n-- > 0) + atom = atom->next(); } } - endText(relative, marker); } + endText(relative, marker); + return true; } #endif @@ -302,7 +306,7 @@ void Generator::generateBody(const Node *node, CodeMarker *marker) } if (node->doc().isEmpty()) { - if (!quiet) // ### might be unnecessary + if (!quiet && !node->isReimp()) // ### might be unnecessary node->location().warning(tr("No documentation for '%1'") .arg(marker->plainFullName(node))); } @@ -313,7 +317,9 @@ void Generator::generateBody(const Node *node, CodeMarker *marker) generateReimplementedFrom(func, marker); } - generateText(node->doc().body(), node, marker); + if (!generateText(node->doc().body(), node, marker)) + if (node->isReimp()) + return; if (node->type() == Node::Enum) { const EnumNode *enume = (const EnumNode *) node; diff --git a/tools/qdoc3/generator.h b/tools/qdoc3/generator.h index 75134d2..08b857b 100644 --- a/tools/qdoc3/generator.h +++ b/tools/qdoc3/generator.h @@ -93,11 +93,11 @@ class Generator virtual void generateClassLikeNode(const InnerNode *inner, CodeMarker *marker); virtual void generateFakeNode(const FakeNode *fake, CodeMarker *marker); - virtual void generateText(const Text& text, + virtual bool generateText(const Text& text, const Node *relative, CodeMarker *marker); #ifdef QDOC_QML - virtual void generateQmlText(const Text& text, + virtual bool generateQmlText(const Text& text, const Node *relative, CodeMarker *marker); #endif diff --git a/tools/qdoc3/javadocgenerator.cpp b/tools/qdoc3/javadocgenerator.cpp index b32425c..294877b 100644 --- a/tools/qdoc3/javadocgenerator.cpp +++ b/tools/qdoc3/javadocgenerator.cpp @@ -272,9 +272,10 @@ void JavadocGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker HtmlGenerator::generateFakeNode(fake, marker); } -void JavadocGenerator::generateText(const Text& text, const Node *relative, CodeMarker *marker) +bool JavadocGenerator::generateText(const Text& text, const Node *relative, CodeMarker *marker) { HtmlGenerator::generateText(text, relative, marker); + return true; } void JavadocGenerator::generateBody(const Node *node, CodeMarker *marker) diff --git a/tools/qdoc3/javadocgenerator.h b/tools/qdoc3/javadocgenerator.h index ba9b15d..5431c38 100644 --- a/tools/qdoc3/javadocgenerator.h +++ b/tools/qdoc3/javadocgenerator.h @@ -68,7 +68,7 @@ protected: void generateClassLikeNode(const InnerNode *inner, CodeMarker *marker); void generateFakeNode( const FakeNode *fake, CodeMarker *marker ); - void generateText( const Text& text, const Node *relative, CodeMarker *marker ); + bool generateText( const Text& text, const Node *relative, CodeMarker *marker ); void generateBody( const Node *node, CodeMarker *marker ); void generateAlsoList( const Node *node, CodeMarker *marker ); diff --git a/tools/qdoc3/node.cpp b/tools/qdoc3/node.cpp index 0f9468a..b2e53ab 100644 --- a/tools/qdoc3/node.cpp +++ b/tools/qdoc3/node.cpp @@ -868,6 +868,18 @@ void FunctionNode::setOverload(bool overlode) } /*! + Sets the function node's reimplementation flag to \a r. + When \a r is true, it is supposed to mean that this function + is a reimplementation of a virtual function in a base class, + but it really just means the \e reimp command was seen in the + qdoc comment. + */ +void FunctionNode::setReimp(bool r) +{ + reimp = r; +} + +/*! */ void FunctionNode::addParameter(const Parameter& parameter) { diff --git a/tools/qdoc3/node.h b/tools/qdoc3/node.h index 0a671b37d..a35bc17 100644 --- a/tools/qdoc3/node.h +++ b/tools/qdoc3/node.h @@ -123,6 +123,7 @@ class Node void setTemplateStuff(const QString &templateStuff) { tpl = templateStuff; } virtual bool isInnerNode() const = 0; + virtual bool isReimp() const { return false; } Type type() const { return typ; } InnerNode *parent() const { return par; } InnerNode *relates() const { return rel; } @@ -444,6 +445,7 @@ class FunctionNode : public LeafNode void setConst(bool conste) { con = conste; } void setStatic(bool statique) { sta = statique; } void setOverload(bool overlode); + void setReimp(bool r); void addParameter(const Parameter& parameter); inline void setParameters(const QList& parameters); void borrowParameterNames(const FunctionNode *source); @@ -458,6 +460,7 @@ class FunctionNode : public LeafNode bool isConst() const { return con; } bool isStatic() const { return sta; } bool isOverload() const { return ove; } + bool isReimp() const { return reimp; } int overloadNumber() const; int numOverloads() const; const QList& parameters() const { return params; } @@ -483,6 +486,7 @@ class FunctionNode : public LeafNode bool con : 1; bool sta : 1; bool ove : 1; + bool reimp: 1; QList params; const FunctionNode *rf; const PropertyNode *ap; -- cgit v0.12 From 548274de342d6b14de57c96c484e02118b858d4a Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Tue, 30 Jun 2009 13:55:30 +0200 Subject: doc: Fixed several qdoc error reports. --- src/gui/graphicsview/qgraphicswidget.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp index 0644ce9..86c0b48 100644 --- a/src/gui/graphicsview/qgraphicswidget.cpp +++ b/src/gui/graphicsview/qgraphicswidget.cpp @@ -971,15 +971,18 @@ void QGraphicsWidget::updateGeometry() deliver events related to state changes in the item. Because of this, it is very important that subclasses call the base implementation. - For example, QGraphicsWidget uses ItemVisibleChange to deliver \l Show and - \l Hide events, ItemPositionHasChanged to deliver \l Move events, and - ItemParentChange both to deliver \l ParentChange events, and for managing - the focus chain. + \a change specifies the type of change, and \a value is the new value. + + For example, QGraphicsWidget uses ItemVisibleChange to deliver + \l{QEvent::Show} {Show} and \l{QEvent::Hide}{Hide} events, + ItemPositionHasChanged to deliver \l{QEvent::Move}{Move} events, + and ItemParentChange both to deliver \l{QEvent::ParentChange} + {ParentChange} events, and for managing the focus chain. QGraphicsWidget enables the ItemSendsGeometryChanges flag by default in order to track position changes. - \sa propertyChange() + \sa QGraphicsItem::itemChange() */ QVariant QGraphicsWidget::itemChange(GraphicsItemChange change, const QVariant &value) { @@ -1211,7 +1214,8 @@ Qt::WindowFrameSection QGraphicsWidget::windowFrameSectionAt(const QPointF &pos) /*! \reimp - QGraphicsWidget handles the following events: + Handles the \a event. QGraphicsWidget handles the following + events: \table \o Event \o Usage \row \o Polish -- cgit v0.12 From 4d8567b85bf14b1515aafc97c035b2dda2c79b2a Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Tue, 30 Jun 2009 14:16:07 +0200 Subject: QToolBar: fix coverity warnings I also changed a bit the way the timer for the popup is working --- src/gui/widgets/qtoolbar.cpp | 36 ++++++++++++++---------------------- src/gui/widgets/qtoolbar.h | 1 - src/gui/widgets/qtoolbar_p.h | 8 ++++---- 3 files changed, 18 insertions(+), 27 deletions(-) diff --git a/src/gui/widgets/qtoolbar.cpp b/src/gui/widgets/qtoolbar.cpp index b635628..3414b4f 100644 --- a/src/gui/widgets/qtoolbar.cpp +++ b/src/gui/widgets/qtoolbar.cpp @@ -70,6 +70,8 @@ #include "qdebug.h" +#define POPUP_TIMER_INTERVAL 500 + QT_BEGIN_NAMESPACE #ifdef Q_WS_MAC @@ -87,14 +89,6 @@ static void qt_mac_updateToolBarButtonHint(QWidget *parentWidget) void QToolBarPrivate::init() { Q_Q(QToolBar); - - waitForPopupTimer = new QTimer(q); - waitForPopupTimer->setSingleShot(false); - waitForPopupTimer->setInterval(500); - QObject::connect(waitForPopupTimer, SIGNAL(timeout()), q, SLOT(_q_waitForPopup())); - - floatable = true; - movable = true; q->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed)); q->setBackgroundRole(QPalette::Button); q->setAttribute(Qt::WA_Hover); @@ -1086,6 +1080,16 @@ bool QToolBar::event(QEvent *event) Q_D(QToolBar); switch (event->type()) { + case QEvent::Timer: + if (d->waitForPopupTimer.timerId() == static_cast(event)->timerId()) { + QWidget *w = QApplication::activePopupWidget(); + if (!waitForPopup(this, w)) { + d->waitForPopupTimer.stop(); + if (!this->underMouse()) + d->layout->setExpanded(false); + } + } + break; case QEvent::Hide: if (!isHidden()) break; @@ -1183,11 +1187,11 @@ bool QToolBar::event(QEvent *event) QWidget *w = QApplication::activePopupWidget(); if (waitForPopup(this, w)) { - d->waitForPopupTimer->start(); + d->waitForPopupTimer.start(POPUP_TIMER_INTERVAL, this); break; } - d->waitForPopupTimer->stop(); + d->waitForPopupTimer.stop(); d->layout->setExpanded(false); break; } @@ -1197,18 +1201,6 @@ bool QToolBar::event(QEvent *event) return QWidget::event(event); } -void QToolBarPrivate::_q_waitForPopup() -{ - Q_Q(QToolBar); - - QWidget *w = QApplication::activePopupWidget(); - if (!waitForPopup(q, w)) { - waitForPopupTimer->stop(); - if (!q->underMouse()) - layout->setExpanded(false); - } -} - /*! Returns a checkable action that can be used to show or hide this toolbar. diff --git a/src/gui/widgets/qtoolbar.h b/src/gui/widgets/qtoolbar.h index 2ab4ffd..07502b3 100644 --- a/src/gui/widgets/qtoolbar.h +++ b/src/gui/widgets/qtoolbar.h @@ -167,7 +167,6 @@ private: Q_PRIVATE_SLOT(d_func(), void _q_toggleView(bool)) Q_PRIVATE_SLOT(d_func(), void _q_updateIconSize(const QSize &)) Q_PRIVATE_SLOT(d_func(), void _q_updateToolButtonStyle(Qt::ToolButtonStyle)) - Q_PRIVATE_SLOT(d_func(), void _q_waitForPopup()) friend class QMainWindow; friend class QMainWindowLayout; diff --git a/src/gui/widgets/qtoolbar_p.h b/src/gui/widgets/qtoolbar_p.h index b03c460..42ea97f 100644 --- a/src/gui/widgets/qtoolbar_p.h +++ b/src/gui/widgets/qtoolbar_p.h @@ -56,6 +56,7 @@ #include "qtoolbar.h" #include "QtGui/qaction.h" #include "private/qwidget_p.h" +#include QT_BEGIN_NAMESPACE @@ -70,7 +71,7 @@ class QToolBarPrivate : public QWidgetPrivate public: inline QToolBarPrivate() - : explicitIconSize(false), explicitToolButtonStyle(false), movable(false), + : explicitIconSize(false), explicitToolButtonStyle(false), movable(true), floatable(true), allowedAreas(Qt::AllToolBarAreas), orientation(Qt::Horizontal), toolButtonStyle(Qt::ToolButtonIconOnly), layout(0), state(0) @@ -84,16 +85,15 @@ public: void _q_toggleView(bool b); void _q_updateIconSize(const QSize &sz); void _q_updateToolButtonStyle(Qt::ToolButtonStyle style); - void _q_waitForPopup(); bool explicitIconSize; bool explicitToolButtonStyle; bool movable; + bool floatable; Qt::ToolBarAreas allowedAreas; Qt::Orientation orientation; Qt::ToolButtonStyle toolButtonStyle; QSize iconSize; - bool floatable; QAction *toggleViewAction; @@ -125,7 +125,7 @@ public: void unplug(const QRect &r); void plug(const QRect &r); - QTimer *waitForPopupTimer; + QBasicTimer waitForPopupTimer; }; #endif // QT_NO_TOOLBAR -- cgit v0.12 From 951ee7c2995b4f5c1a61c72c8f53ff40a3a0b2d4 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Tue, 30 Jun 2009 14:52:13 +0200 Subject: QDockArea: remove coverity warning --- src/gui/widgets/qdockarealayout.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/widgets/qdockarealayout.cpp b/src/gui/widgets/qdockarealayout.cpp index 9828413..f245d64 100644 --- a/src/gui/widgets/qdockarealayout.cpp +++ b/src/gui/widgets/qdockarealayout.cpp @@ -2074,7 +2074,7 @@ void QDockAreaLayoutInfo::updateTabBar() const QDockAreaLayoutInfo *that = const_cast(this); - if (tabBar == 0) { + if (that->tabBar == 0) { that->tabBar = mainWindowLayout()->getTabBar(); that->tabBar->setShape(static_cast(tabBarShape)); that->tabBar->setDrawBase(true); -- cgit v0.12 From 6ee3fb750377eeedf161d96fef02c5fa336810e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Tue, 30 Jun 2009 13:00:32 +0200 Subject: More re-factoring of QGraphicsSceneIndex. Mostly re-factoring of QGraphicsSceneIndexPrivate::recursive_items_helper so it can re-use code from the scene (topLevelItemsInStackingOrder). That also means we'll use the bsp tree in case of NoIndex instead of always looping through the top-levels. This function is now almost identical to QGraphicsScenePrivate::drawSubtreeRecursive, so it might be worth looking into how we can abstract it even more and have one common recursive function. --- src/gui/graphicsview/qgraphicsscene.cpp | 20 +--- src/gui/graphicsview/qgraphicsscene_p.h | 11 +- .../graphicsview/qgraphicsscenebsptreeindex_p.h | 12 +-- src/gui/graphicsview/qgraphicssceneindex.cpp | 115 ++++++++------------- src/gui/graphicsview/qgraphicssceneindex_p.h | 34 ++++-- 5 files changed, 89 insertions(+), 103 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index f1e56c1..faacf4d 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -217,8 +217,9 @@ #include "qgraphicsview_p.h" #include "qgraphicswidget.h" #include "qgraphicswidget_p.h" -#include -#include +#include "qgraphicssceneindex_p.h" +#include "qgraphicsscenebsptreeindex_p.h" +#include "qgraphicsscenelinearindex_p.h" #include #include @@ -243,7 +244,6 @@ #include #include #include -#include #include #ifdef Q_WS_X11 #include @@ -1075,9 +1075,9 @@ QGraphicsWidget *QGraphicsScenePrivate::windowForItem(const QGraphicsItem *item) } QList QGraphicsScenePrivate::topLevelItemsInStackingOrder(const QTransform *const viewTransform, - QRegion *exposedRegion) + const QRectF &sceneRect) { - if (indexMethod == QGraphicsScene::NoIndex || !exposedRegion) { + if (indexMethod == QGraphicsScene::NoIndex || sceneRect.isNull()) { if (needSortTopLevelItems) { needSortTopLevelItems = false; qStableSort(topLevelItems.begin(), topLevelItems.end(), qt_notclosestLeaf); @@ -1085,16 +1085,6 @@ QList QGraphicsScenePrivate::topLevelItemsInStackingOrder(const return topLevelItems; } - const QRectF exposedRect = exposedRegion->boundingRect().adjusted(-1, -1, 1, 1); - QRectF sceneRect; - QTransform invertedViewTransform(Qt::Uninitialized); - if (!viewTransform) { - sceneRect = exposedRect; - } else { - invertedViewTransform = viewTransform->inverted(); - sceneRect = invertedViewTransform.mapRect(exposedRect); - } - QList tmp = index->estimateItems(sceneRect, Qt::SortOrder(-1), viewTransform ? *viewTransform : QTransform()); for (int i = 0; i < tmp.size(); ++i) { diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index f286a8d..b3d7535 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -57,7 +57,6 @@ #if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW -#include "qgraphicsscenebsptreeindex_p.h" #include "qgraphicsview.h" #include "qgraphicsitem_p.h" @@ -187,7 +186,7 @@ public: QGraphicsWidget *windowForItem(const QGraphicsItem *item) const; bool sortCacheEnabled; // for compatibility - QList topLevelItemsInStackingOrder(const QTransform *const, QRegion *); + QList topLevelItemsInStackingOrder(const QTransform *const, const QRectF&); void drawItemHelper(QGraphicsItem *item, QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget, @@ -196,7 +195,13 @@ public: inline void drawItems(QPainter *painter, const QTransform *const viewTransform, QRegion *exposedRegion, QWidget *widget) { - const QList tli = topLevelItemsInStackingOrder(viewTransform, exposedRegion); + QRectF exposedSceneRect; + if (exposedRegion && indexMethod != QGraphicsScene::NoIndex) { + exposedSceneRect = exposedRegion->boundingRect().adjusted(-1, -1, 1, 1); + if (viewTransform) + exposedSceneRect = viewTransform->inverted().mapRect(exposedSceneRect); + } + const QList tli = topLevelItemsInStackingOrder(viewTransform, exposedSceneRect); for (int i = 0; i < tli.size(); ++i) drawSubtreeRecursive(tli.at(i), painter, viewTransform, exposedRegion, widget); return; diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h index 850cc3f..90cc8c3 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h @@ -39,8 +39,6 @@ ** ****************************************************************************/ -#include - // // W A R N I N G // ------------- @@ -63,13 +61,13 @@ QT_MODULE(Gui) #if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW +#include "qgraphicssceneindex_p.h" +#include "qgraphicsitem_p.h" +#include "qgraphicsscene_bsp_p.h" + +#include #include #include -#include -#include -#include -#include -#include static const int QGRAPHICSSCENE_INDEXTIMER_TIMEOUT = 2000; diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index 88fb6b0..a42dc54 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -61,7 +61,8 @@ #include "qgraphicsitem_p.h" #include "qgraphicsscene_p.h" #include "qgraphicswidget.h" -#include +#include "qgraphicssceneindex_p.h" +#include "qgraphicsscenebsptreeindex_p.h" #ifndef QT_NO_GRAPHICSVIEW @@ -240,91 +241,64 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRe Qt::ItemSelectionMode mode, Qt::SortOrder order, qreal parentOpacity) const { - // Calculate opacity. - qreal opacity; - if (item) { - if (!item->d_ptr->visible) - return; + Q_ASSERT(item); + if (!item->d_ptr->visible) + return; - QGraphicsItem *p = item->d_ptr->parent; - bool itemIgnoresParentOpacity = item->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity; - bool parentDoesntPropagateOpacity = (p && (p->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)); - if (!itemIgnoresParentOpacity && !parentDoesntPropagateOpacity) { - opacity = parentOpacity * item->opacity(); - } else { - opacity = item->d_ptr->opacity; - } - if (opacity == 0.0 && !(item->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) - return; - } else { - opacity = parentOpacity; - } + const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity); + const bool itemIsFullyTransparent = (opacity < 0.0001); + const bool itemHasChildren = !item->d_ptr->children.isEmpty(); + if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity())) + return; // Calculate the full transform for this item. - QTransform transform = parentTransform; - bool keep = false; - if (item) { - item->d_ptr->combineTransformFromParent(&transform, &viewTransform); - - // ### This does not take the clip into account. - QRectF brect = item->boundingRect(); - _q_adjustRect(&brect); - - //We fill the intersector with needed informations - keep = intersector->intersect(item, exposeRect, mode, transform, viewTransform); - } - - bool childClip = (item && (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)); - bool dontProcessItem = !item || !keep; - bool dontProcessChildren = item && dontProcessItem && childClip; + QTransform transform(parentTransform); + item->d_ptr->combineTransformFromParent(&transform, &viewTransform); + + const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape); + bool processItem = !itemIsFullyTransparent; + if (processItem) { + processItem = intersector->intersect(item, exposeRect, mode, transform, viewTransform); + if (!processItem && (!itemHasChildren || itemClipsChildrenToShape)) + return; + } // else we know for sure this item has children we must process. - // Find and sort children. - QList &children = item ? item->d_ptr->children : const_cast(scene->d_func())->topLevelItems; - if (!dontProcessChildren) { - if (item && item->d_ptr->needSortChildren) { + int i = 0; + if (itemHasChildren) { + // Sort children. + if (item->d_ptr->needSortChildren) { item->d_ptr->needSortChildren = 0; - qStableSort(children.begin(), children.end(), qt_notclosestLeaf); - } else if (!item && scene->d_func()->needSortTopLevelItems) { - const_cast(scene->d_func())->needSortTopLevelItems = false; - qStableSort(children.begin(), children.end(), qt_notclosestLeaf); + qStableSort(item->d_ptr->children.begin(), item->d_ptr->children.end(), qt_notclosestLeaf); } - } - - childClip &= !dontProcessChildren & !children.isEmpty(); - // Clip. - if (childClip) - exposeRect &= transform.map(item->shape()).controlPointRect(); + // Clip to shape. + if (itemClipsChildrenToShape) + exposeRect &= transform.map(item->shape()).controlPointRect(); - // Process children behind - int i = 0; - if (!dontProcessChildren) { - for (i = 0; i < children.size(); ++i) { - QGraphicsItem *child = children.at(i); + // Process children behind + for (i = 0; i < item->d_ptr->children.size(); ++i) { + QGraphicsItem *child = item->d_ptr->children.at(i); if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent)) break; + if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity)) + continue; recursive_items_helper(child, exposeRect, intersector, items, transform, viewTransform, mode, order, opacity); } } // Process item - if (!dontProcessItem) + if (processItem) items->append(item); // Process children in front - if (!dontProcessChildren) { - for (; i < children.size(); ++i) - recursive_items_helper(children.at(i), exposeRect, intersector, items, transform, viewTransform, + if (itemHasChildren) { + for (; i < item->d_ptr->children.size(); ++i) { + QGraphicsItem *child = item->d_ptr->children.at(i); + if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity)) + continue; + recursive_items_helper(child, exposeRect, intersector, items, transform, viewTransform, mode, order, opacity); - } - - if (!item && order == Qt::AscendingOrder) { - int n = items->size(); - for (int i = 0; i < n / 2; ++i) { - QGraphicsItem *tmp = (*items)[n - i - 1]; - (*items)[n - i - 1] = (*items)[i]; - (*items)[i] = tmp; } } } @@ -393,8 +367,7 @@ QList QGraphicsSceneIndex::items(const QPointF &pos, Qt::ItemSe Q_D(const QGraphicsSceneIndex); QList itemList; d->pointIntersector->scenePoint = pos; - d->recursive_items_helper(0, QRectF(pos, QSizeF(1, 1)), d->pointIntersector, &itemList, - QTransform(), deviceTransform, mode, order); + d->items_helper(QRectF(pos, QSizeF(1, 1)), d->pointIntersector, &itemList, deviceTransform, mode, order); return itemList; } @@ -428,7 +401,7 @@ QList QGraphicsSceneIndex::items(const QRectF &rect, Qt::ItemSe _q_adjustRect(&exposeRect); QList itemList; d->rectIntersector->sceneRect = rect; - d->recursive_items_helper(0, exposeRect, d->rectIntersector, &itemList, QTransform(), deviceTransform, mode, order); + d->items_helper(exposeRect, d->rectIntersector, &itemList, deviceTransform, mode, order); return itemList; } @@ -464,7 +437,7 @@ QList QGraphicsSceneIndex::items(const QPolygonF &polygon, Qt:: QPainterPath path; path.addPolygon(polygon); d->pathIntersector->scenePath = path; - d->recursive_items_helper(0, exposeRect, d->pathIntersector, &itemList, QTransform(), deviceTransform, mode, order); + d->items_helper(exposeRect, d->pathIntersector, &itemList, deviceTransform, mode, order); return itemList; } @@ -498,7 +471,7 @@ QList QGraphicsSceneIndex::items(const QPainterPath &path, Qt:: QRectF exposeRect = path.controlPointRect(); _q_adjustRect(&exposeRect); d->pathIntersector->scenePath = path; - d->recursive_items_helper(0, exposeRect, d->pathIntersector, &itemList, QTransform(), deviceTransform, mode, order); + d->items_helper(exposeRect, d->pathIntersector, &itemList, deviceTransform, mode, order); return itemList; } diff --git a/src/gui/graphicsview/qgraphicssceneindex_p.h b/src/gui/graphicsview/qgraphicssceneindex_p.h index dc6a740..122d7ae 100644 --- a/src/gui/graphicsview/qgraphicssceneindex_p.h +++ b/src/gui/graphicsview/qgraphicssceneindex_p.h @@ -53,11 +53,13 @@ // We mean it. // +#include "qgraphicsscene_p.h" +#include "qgraphicsscene.h" +#include + #include #include #include -#include -#include QT_BEGIN_HEADER @@ -67,7 +69,6 @@ QT_MODULE(Gui) #if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW -class QGraphicsScene; class QGraphicsSceneIndexIntersector; class QGraphicsSceneIndexPointIntersector; class QGraphicsSceneIndexRectIntersector; @@ -138,12 +139,31 @@ public: QGraphicsSceneIndexIntersector *intersector, QList *items, const QTransform &parentTransform, const QTransform &viewTransform, Qt::ItemSelectionMode mode, Qt::SortOrder order, qreal parentOpacity = 1.0) const; - QGraphicsScene *scene; - QGraphicsSceneIndexPointIntersector *pointIntersector; - QGraphicsSceneIndexRectIntersector *rectIntersector; - QGraphicsSceneIndexPathIntersector *pathIntersector; + inline void items_helper(const QRectF &rect, QGraphicsSceneIndexIntersector *intersector, + QList *items, const QTransform &viewTransform, + Qt::ItemSelectionMode mode, Qt::SortOrder order) const; + + QGraphicsScene *scene; + QGraphicsSceneIndexPointIntersector *pointIntersector; + QGraphicsSceneIndexRectIntersector *rectIntersector; + QGraphicsSceneIndexPathIntersector *pathIntersector; }; +inline void QGraphicsSceneIndexPrivate::items_helper(const QRectF &rect, QGraphicsSceneIndexIntersector *intersector, + QList *items, const QTransform &viewTransform, + Qt::ItemSelectionMode mode, Qt::SortOrder order) const +{ + const QList tli = scene->d_func()->topLevelItemsInStackingOrder(&viewTransform, rect); + const QTransform identity; + for (int i = 0; i < tli.size(); ++i) + recursive_items_helper(tli.at(i), rect, intersector, items, identity, viewTransform, mode, order); + if (order == Qt::AscendingOrder) { + const int n = items->size(); + for (int i = 0; i < n / 2; ++i) + items->swap(i, n - i - 1); + } +} + class QGraphicsSceneIndexIntersector { public: -- cgit v0.12 From 771a6a8fd6a31905859a40b729eac872efb20285 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Tue, 30 Jun 2009 15:19:10 +0200 Subject: Linguist: defers the creation of the QPrinter On windows, if your default printer is not reachable it would take a lot of time to fail to construct the print engine. During that time the UI would be frozen on the splash screen. Reviewed-by: ossi --- tools/linguist/linguist/mainwindow.cpp | 22 ++++++++++++++++------ tools/linguist/linguist/mainwindow.h | 6 ++++-- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/tools/linguist/linguist/mainwindow.cpp b/tools/linguist/linguist/mainwindow.cpp index 2b1df39..bb79b19 100644 --- a/tools/linguist/linguist/mainwindow.cpp +++ b/tools/linguist/linguist/mainwindow.cpp @@ -82,6 +82,7 @@ #include #include #include +#include #include #include #include @@ -257,6 +258,7 @@ bool FocusWatcher::eventFilter(QObject *, QEvent *event) MainWindow::MainWindow() : QMainWindow(0, Qt::Window), m_assistantProcess(0), + m_printer(0), m_findMatchCase(Qt::CaseInsensitive), m_findIgnoreAccelerators(true), m_findWhere(DataModel::NoLocation), @@ -503,6 +505,7 @@ MainWindow::~MainWindow() qDeleteAll(m_phraseBooks); delete m_dataModel; delete m_statistics; + delete m_printer; } void MainWindow::modelCountChanged() @@ -870,15 +873,22 @@ void MainWindow::releaseAll() releaseInternal(i); } +QPrinter *MainWindow::printer() +{ + if (!m_printer) + m_printer = new QPrinter; + return m_printer; +} + void MainWindow::print() { int pageNum = 0; - QPrintDialog dlg(&m_printer, this); + QPrintDialog dlg(printer(), this); if (dlg.exec()) { QApplication::setOverrideCursor(Qt::WaitCursor); - m_printer.setDocName(m_dataModel->condensedSrcFileNames(true)); + printer()->setDocName(m_dataModel->condensedSrcFileNames(true)); statusBar()->showMessage(tr("Printing...")); - PrintOut pout(&m_printer); + PrintOut pout(printer()); for (int i = 0; i < m_dataModel->contextCount(); ++i) { MultiContextItem *mc = m_dataModel->multiContextItem(i); @@ -1229,11 +1239,11 @@ void MainWindow::printPhraseBook(QAction *action) int pageNum = 0; - QPrintDialog dlg(&m_printer, this); + QPrintDialog dlg(printer(), this); if (dlg.exec()) { - m_printer.setDocName(phraseBook->fileName()); + printer()->setDocName(phraseBook->fileName()); statusBar()->showMessage(tr("Printing...")); - PrintOut pout(&m_printer); + PrintOut pout(printer()); pout.setRule(PrintOut::ThinRule); foreach (const Phrase *p, phraseBook->phrases()) { pout.setGuide(p->source()); diff --git a/tools/linguist/linguist/mainwindow.h b/tools/linguist/linguist/mainwindow.h index 167dfe4..3dedcb5 100644 --- a/tools/linguist/linguist/mainwindow.h +++ b/tools/linguist/linguist/mainwindow.h @@ -51,7 +51,6 @@ #include #include -#include QT_BEGIN_NAMESPACE @@ -60,6 +59,7 @@ class QAction; class QDialog; class QLabel; class QMenu; +class QPrinter; class QProcess; class QIcon; class QSortFilterProxyModel; @@ -200,6 +200,8 @@ private: void releaseInternal(int model); void saveInternal(int model); + QPrinter *printer(); + // FIXME: move to DataModel void updateDanger(const MultiDataIndex &index, bool verbose); @@ -226,7 +228,7 @@ private: QList > > m_phraseDict; QList m_phraseBooks; QMap m_phraseBookMenu[3]; - QPrinter m_printer; + QPrinter *m_printer; FindDialog *m_findDialog; QString m_findText; -- cgit v0.12 From 99bea47fd9b868fb22f175943c11ecb05b51f07c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Tue, 30 Jun 2009 15:54:19 +0200 Subject: Fix broken tst_QGraphicsView::embeddedViews. This test has been broken after 32f32ee3e752a6cc03505ddaa48d2849eaedc2a6, but the test continued to pass because another bug, which is fixed by 6ee3fb750377eeedf161d96fef02c5fa336810e9. The transform should be exactly the same in both cases. --- tests/auto/qgraphicsview/tst_qgraphicsview.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp index 65e066f..6db8f27 100644 --- a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp +++ b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp @@ -2989,14 +2989,7 @@ void tst_QGraphicsView::embeddedViews() v2->QWidget::render(&actual); QTransform b = item->transform; -#ifdef Q_WS_MAC - // We don't use shared painter on the Mac, so the - // transform should be exactly the same. QVERIFY(a == b); -#else - QVERIFY(a != b); -#endif - delete v1; } -- cgit v0.12 From 6c3412bf598c2bcf8863c08e16d7a80b119ff116 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Tue, 30 Jun 2009 15:58:58 +0200 Subject: add basic tests for QVariant/QObject qtscript integration Some of the more advanced tests will fail for non-obvious reasons if these basic assumptions don't hold. --- tests/auto/qscriptqobject/tst_qscriptqobject.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/auto/qscriptqobject/tst_qscriptqobject.cpp b/tests/auto/qscriptqobject/tst_qscriptqobject.cpp index d8db7b7..14d3283 100644 --- a/tests/auto/qscriptqobject/tst_qscriptqobject.cpp +++ b/tests/auto/qscriptqobject/tst_qscriptqobject.cpp @@ -736,6 +736,8 @@ void tst_QScriptExtQObject::getSetStaticProperty() // test that we do value conversion if necessary when setting properties { QScriptValue br = m_engine->evaluate("myObject.brushProperty"); + QVERIFY(br.isVariant()); + QVERIFY(!br.strictlyEquals(m_engine->evaluate("myObject.brushProperty"))); QCOMPARE(qscriptvalue_cast(br), m_myObject->brushProperty()); QCOMPARE(qscriptvalue_cast(br), m_myObject->brushProperty().color()); @@ -838,6 +840,14 @@ void tst_QScriptExtQObject::getSetStaticProperty() mobj.setProperty("intProperty", m_engine->newFunction(getSetProperty), QScriptValue::PropertyGetter | QScriptValue::PropertySetter); } + + // method properties are persistent + { + QScriptValue slot = m_engine->evaluate("myObject.mySlot"); + QVERIFY(slot.isFunction()); + QScriptValue sameSlot = m_engine->evaluate("myObject.mySlot"); + QVERIFY(sameSlot.strictlyEquals(slot)); + } } void tst_QScriptExtQObject::getSetDynamicProperty() -- cgit v0.12 From 3a00930fe167e6db5588d9e93d429486f9591bd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Tue, 30 Jun 2009 16:15:28 +0200 Subject: More BSP tree index cleanup. Ensure the index of indexed items are reset to -1. Makes tst_QGraphicsScene::itemIndexMethod happy. (this test passed before we actually started using the BSP from the items() functions, see 6ee3fb750377eeedf161d96fef02c5fa336810e9) --- src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp | 12 ++++++++++++ src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h | 1 + 2 files changed, 13 insertions(+) diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp index 413c8de..ff9a3da 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -468,6 +468,18 @@ QGraphicsSceneBspTreeIndex::QGraphicsSceneBspTreeIndex(QGraphicsScene *scene) } +QGraphicsSceneBspTreeIndex::~QGraphicsSceneBspTreeIndex() +{ + Q_D(QGraphicsSceneBspTreeIndex); + for (int i = 0; i < d->indexedItems.size(); ++i) { + // Ensure item bits are reset properly. + if (QGraphicsItem *item = d->indexedItems.at(i)) { + Q_ASSERT(!item->d_ptr->itemDiscovered); + item->d_ptr->index = -1; + } + } +} + /*! \reimp Clear the all the BSP index. diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h index 90cc8c3..7b431e6 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h @@ -80,6 +80,7 @@ class Q_AUTOTEST_EXPORT QGraphicsSceneBspTreeIndex : public QGraphicsSceneIndex Q_PROPERTY(int bspTreeDepth READ bspTreeDepth WRITE setBspTreeDepth) public: QGraphicsSceneBspTreeIndex(QGraphicsScene *scene = 0); + ~QGraphicsSceneBspTreeIndex(); QList estimateItems(const QRectF &rect, Qt::SortOrder order, const QTransform &deviceTransform) const; -- cgit v0.12 From 53ef0b0f8b1227cff6ce4c9e2a91a6fbc7e7ee3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Tue, 30 Jun 2009 16:19:25 +0200 Subject: Make QGraphicsSceneIndex::clear() less nasty. --- src/gui/graphicsview/qgraphicssceneindex.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index a42dc54..2f2f05e 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -521,8 +521,9 @@ void QGraphicsSceneIndex::updateSceneRect(const QRectF &rect) */ void QGraphicsSceneIndex::clear() { - for (int i = 0 ; i < items().size(); ++i) - removeItem(items().at(i)); + const QList allItems = items(); + for (int i = 0 ; i < allItems.size(); ++i) + removeItem(allItems.at(i)); } /*! -- cgit v0.12 From 3687425e541bd5f78c7baf63cfa5b1ba4d9ad29e Mon Sep 17 00:00:00 2001 From: Kavindra Devi Palaraja Date: Tue, 30 Jun 2009 16:52:11 +0200 Subject: Doc - some minor fixes on the sentences Reviewed-By: TrustMe --- doc/src/tutorials/addressbook.qdoc | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/doc/src/tutorials/addressbook.qdoc b/doc/src/tutorials/addressbook.qdoc index 2f6cec2..23dabb3 100644 --- a/doc/src/tutorials/addressbook.qdoc +++ b/doc/src/tutorials/addressbook.qdoc @@ -697,10 +697,11 @@ \snippet tutorials/addressbook/part5/finddialog.h FindDialog header - We define a public function, \c getFindText() for use by classes that - instantiate \c FindDialog, which allows them to obtain the text - entered by the user. A public slot, \c findClicked(), is defined to - handle the search string when the user clicks the \gui Find button. + We define a public function, \c getFindText(), to be used by classes that + instantiate \c FindDialog. This function allows these classes to obtain the + search string entered by the user. A public slot, \c findClicked(), is also + defined to handle the search string when the user clicks the \gui Find + button. Lastly, we define the private variables, \c findButton, \c lineEdit and \c findText, corresponding to the \gui Find button, the line edit @@ -715,15 +716,15 @@ \snippet tutorials/addressbook/part5/finddialog.cpp constructor - We set the layout and window title, as well as connect the signals - to their respective slots. Notice that \c{findButton}'s - \l{QPushButton::clicked()}{clicked()} signal is connected to to - \c findClicked() and \l{QDialog::accept()}{accept()}. The - \l{QDialog::accept()}{accept()} slot provided by QDialog hides - the dialog and sets the result code to \l{QDialog::}{Accepted}. - We use this function to help \c{AddressBook}'s \c findContact() function - know when the \c FindDialog object has been closed. This will be - further explained when discussing the \c findContact() function. + We set the layout and window title, as well as connect the signals to their + respective slots. Notice that \c{findButton}'s \l{QPushButton::clicked()} + {clicked()} signal is connected to to \c findClicked() and + \l{QDialog::accept()}{accept()}. The \l{QDialog::accept()}{accept()} slot + provided by QDialog hides the dialog and sets the result code to + \l{QDialog::}{Accepted}. We use this function to help \c{AddressBook}'s + \c findContact() function know when the \c FindDialog object has been + closed. We will explain this logic in further detail when discussing the + \c findContact() function. \image addressbook-tutorial-part5-signals-and-slots.png -- cgit v0.12 From e0463464773f5eb2bda98a467a9c91092a1f1964 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 30 Jun 2009 14:11:38 +0200 Subject: const ref for foreach() --- tools/linguist/lupdate/cpp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/linguist/lupdate/cpp.cpp b/tools/linguist/lupdate/cpp.cpp index eb743c2..09148e7 100644 --- a/tools/linguist/lupdate/cpp.cpp +++ b/tools/linguist/lupdate/cpp.cpp @@ -1799,7 +1799,7 @@ void loadCPP(Translator &translator, const QStringList &filenames, ConversionDat ? translator.codecName() : cd.m_codecForSource; QTextCodec *codec = QTextCodec::codecForName(codecName); - foreach (const QString filename, filenames) { + foreach (const QString &filename, filenames) { if (CppFiles::getResults(filename) || CppFiles::isBlacklisted(filename)) continue; -- cgit v0.12 From 7e91986c352677d4c0456d30e1cb5fc3179e28c3 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 30 Jun 2009 18:02:00 +0200 Subject: add 4.6 specific modifications to linguist tools tests --- .../testdata/good/lacksqobject/expectedoutput.txt | 8 +++-- .../testdata/good/parsecpp2/expectedoutput.txt | 7 ++++ .../lupdate/testdata/good/parsecpp2/main.cpp | 24 +++++++++++++ .../lupdate/testdata/good/parsecpp2/main2.cpp | 28 +++++++++++++++ .../lupdate/testdata/good/parsecpp2/main3.cpp | 42 ++++++++++++++++++++++ .../lupdate/testdata/good/parsecpp2/project.pro | 12 +++++++ .../testdata/good/parsecpp2/project.ts.result | 4 +++ 7 files changed, 123 insertions(+), 2 deletions(-) create mode 100644 tests/auto/linguist/lupdate/testdata/good/parsecpp2/expectedoutput.txt create mode 100644 tests/auto/linguist/lupdate/testdata/good/parsecpp2/main.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/parsecpp2/main2.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/parsecpp2/main3.cpp create mode 100644 tests/auto/linguist/lupdate/testdata/good/parsecpp2/project.pro create mode 100644 tests/auto/linguist/lupdate/testdata/good/parsecpp2/project.ts.result diff --git a/tests/auto/linguist/lupdate/testdata/good/lacksqobject/expectedoutput.txt b/tests/auto/linguist/lupdate/testdata/good/lacksqobject/expectedoutput.txt index 8a0bd11..1a6cfeb 100644 --- a/tests/auto/linguist/lupdate/testdata/good/lacksqobject/expectedoutput.txt +++ b/tests/auto/linguist/lupdate/testdata/good/lacksqobject/expectedoutput.txt @@ -1,4 +1,8 @@ .*/lupdate/testdata/good/lacksqobject/main.cpp:17: Class 'B' lacks Q_OBJECT macro -.*/lupdate/testdata/good/lacksqobject/main.cpp:26: Class 'C' lacks Q_OBJECT macro + +.*/lupdate/testdata/good/lacksqobject/main.cpp:24: Class 'C' lacks Q_OBJECT macro + .*/lupdate/testdata/good/lacksqobject/main.cpp:37: Class 'nsB::B' lacks Q_OBJECT macro -.*/lupdate/testdata/good/lacksqobject/main.cpp:45: Class 'nsB::C' lacks Q_OBJECT macro + +.*/lupdate/testdata/good/lacksqobject/main.cpp:43: Class 'nsB::C' lacks Q_OBJECT macro + diff --git a/tests/auto/linguist/lupdate/testdata/good/parsecpp2/expectedoutput.txt b/tests/auto/linguist/lupdate/testdata/good/parsecpp2/expectedoutput.txt new file mode 100644 index 0000000..e3f7926 --- /dev/null +++ b/tests/auto/linguist/lupdate/testdata/good/parsecpp2/expectedoutput.txt @@ -0,0 +1,7 @@ +.*/lupdate/testdata/good/parsecpp2/main.cpp:10: Excess closing brace .* + +.*/lupdate/testdata/good/parsecpp2/main.cpp:14: Excess closing brace .* + +.*/lupdate/testdata/good/parsecpp2/main.cpp:20: Excess closing brace .* + +.*/lupdate/testdata/good/parsecpp2/main.cpp:24: Excess closing brace .* diff --git a/tests/auto/linguist/lupdate/testdata/good/parsecpp2/main.cpp b/tests/auto/linguist/lupdate/testdata/good/parsecpp2/main.cpp new file mode 100644 index 0000000..eb4a09b --- /dev/null +++ b/tests/auto/linguist/lupdate/testdata/good/parsecpp2/main.cpp @@ -0,0 +1,24 @@ +// IMPORTANT!!!! If you want to add testdata to this file, +// always add it to the end in order to not change the linenumbers of translations!!! + +// nothing here + +// sickness: multi-\ +line c++ comment } (with brace) + +#define This is a closing brace } which was ignored +} // complain here + +#define This is another \ + closing brace } which was ignored +} // complain here + +#define This is another /* comment in } define */\ + something /* comment ) + spanning {multiple} lines */ \ + closing brace } which was ignored +} // complain here + +#define This is another // comment in } define \ + something } comment +} // complain here diff --git a/tests/auto/linguist/lupdate/testdata/good/parsecpp2/main2.cpp b/tests/auto/linguist/lupdate/testdata/good/parsecpp2/main2.cpp new file mode 100644 index 0000000..1c72ac2 --- /dev/null +++ b/tests/auto/linguist/lupdate/testdata/good/parsecpp2/main2.cpp @@ -0,0 +1,28 @@ +// IMPORTANT!!!! If you want to add testdata to this file, +// always add it to the end in order to not change the linenumbers of translations!!! + +// nothing here + +// sickness: multi-\ +line c++ comment } (with brace) + +#define This is a closing brace } which was ignored +} // complain here + +#define This is another \ + closing brace } which was ignored +} // complain here + +#define This is another /* comment in } define */\ + something /* comment ) + spanning {multiple} lines */ \ + closing brace } which was ignored +} // complain here + +#define This is another // comment in } define \ + something } comment +} // complain here + +char somestring[] = "\ + continued\n\ + here and \"quoted\" to activate\n"; diff --git a/tests/auto/linguist/lupdate/testdata/good/parsecpp2/main3.cpp b/tests/auto/linguist/lupdate/testdata/good/parsecpp2/main3.cpp new file mode 100644 index 0000000..731d5cdf --- /dev/null +++ b/tests/auto/linguist/lupdate/testdata/good/parsecpp2/main3.cpp @@ -0,0 +1,42 @@ +// IMPORTANT!!!! If you want to add testdata to this file, +// always add it to the end in order to not change the linenumbers of translations!!! + +// nothing here + +// sickness: multi-\ +line c++ comment } (with brace) + +#define This is a closing brace } which was ignored +} // complain here + +#define This is another \ + closing brace } which was ignored +} // complain here + +#define This is another /* comment in } define */\ + something /* comment ) + spanning {multiple} lines */ \ + closing brace } which was ignored +} // complain here + +#define This is another // comment in } define \ + something } comment +} // complain here + +char somestring[] = "\ + continued\n\ + here and \"quoted\" to activate\n"; + + NSString *scriptSource = @"\ + on SetupNewMail(theRecipientAddress, theSubject, theContent, theAttachmentPath)\n\ + tell application \"Mail\" to activate\n\ + tell application \"Mail\"\n\ + set theMessage to make new outgoing message with properties {visible:true, subject:theSubject, content:theContent}\n\ + tell theMessage\n\ + make new to recipient at end of to recipients with properties {address:theRecipientAddress}\n\ + end tell\n\ + tell content of theMessage\n\ + make new attachment with properties {file name:theAttachmentPath} at after last paragraph\n\ + end tell\n\ + end tell\n\ + end SetupNewMail\n"; diff --git a/tests/auto/linguist/lupdate/testdata/good/parsecpp2/project.pro b/tests/auto/linguist/lupdate/testdata/good/parsecpp2/project.pro new file mode 100644 index 0000000..7547a8d --- /dev/null +++ b/tests/auto/linguist/lupdate/testdata/good/parsecpp2/project.pro @@ -0,0 +1,12 @@ +TEMPLATE = app +LANGUAGE = C++ + +SOURCES = main.cpp + +TRANSLATIONS += project.ts + +exists( $$TRANSLATIONS ) { + win32: system(del $$TRANSLATIONS) + unix: system(rm $$TRANSLATIONS) +} + diff --git a/tests/auto/linguist/lupdate/testdata/good/parsecpp2/project.ts.result b/tests/auto/linguist/lupdate/testdata/good/parsecpp2/project.ts.result new file mode 100644 index 0000000..07a7469 --- /dev/null +++ b/tests/auto/linguist/lupdate/testdata/good/parsecpp2/project.ts.result @@ -0,0 +1,4 @@ + + + + -- cgit v0.12 From a1d5b33bd33ecf1d809346a39d2386cafaf50cef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Tue, 30 Jun 2009 18:41:18 +0200 Subject: Partially revert 7fe4f8ff71cf09bbabbd3438ef637fe408a11c33 We have to ensure that the item's top-level is marked as discovered. This broke the dragandroprobot example after we started using the BSP from QGraphicsSceneIndex::items()* (see 6ee3fb750377eeedf161d96fef02c5fa336810e9) --- src/gui/graphicsview/qgraphicsscene.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index faacf4d..ed1d2f3 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -1087,11 +1087,8 @@ QList QGraphicsScenePrivate::topLevelItemsInStackingOrder(const QList tmp = index->estimateItems(sceneRect, Qt::SortOrder(-1), viewTransform ? *viewTransform : QTransform()); - for (int i = 0; i < tmp.size(); ++i) { - QGraphicsItem *item = tmp.at(i); - if (!item->d_ptr->parent) - item->d_ptr->itemDiscovered = 1; - } + for (int i = 0; i < tmp.size(); ++i) + tmp.at(i)->topLevelItem()->d_ptr->itemDiscovered = 1; // Sort if the toplevel list is unsorted. if (needSortTopLevelItems) { -- cgit v0.12 From 436a71e8950ea5a050f95b5889b85e5fafb2e716 Mon Sep 17 00:00:00 2001 From: Benjamin Poulain Date: Tue, 30 Jun 2009 22:50:48 +0200 Subject: Set the focus to a child widget when set on a QGroupBox When the focus is set on a QGroupBox with the policy NoFocus, the focus should be propagated to one of the child if it accepts the focus. This was failing because QWidget::focusWidget() returns the QGroupBox itself. Task-number: 257158 Reviewed-by: Denis --- src/gui/widgets/qgroupbox.cpp | 5 ++--- tests/auto/qgroupbox/tst_qgroupbox.cpp | 11 +++++++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/gui/widgets/qgroupbox.cpp b/src/gui/widgets/qgroupbox.cpp index 0bfa8c0..2380e78 100644 --- a/src/gui/widgets/qgroupbox.cpp +++ b/src/gui/widgets/qgroupbox.cpp @@ -431,7 +431,7 @@ void QGroupBoxPrivate::_q_fixFocus(Qt::FocusReason reason) { Q_Q(QGroupBox); QWidget *fw = q->focusWidget(); - if (!fw) { + if (!fw || fw == q) { QWidget * best = 0; QWidget * candidate = 0; QWidget * w = q; @@ -449,8 +449,7 @@ void QGroupBoxPrivate::_q_fixFocus(Qt::FocusReason reason) } if (best) fw = best; - else - if (candidate) + else if (candidate) fw = candidate; } if (fw) diff --git a/tests/auto/qgroupbox/tst_qgroupbox.cpp b/tests/auto/qgroupbox/tst_qgroupbox.cpp index 2fa553f..3b94851 100644 --- a/tests/auto/qgroupbox/tst_qgroupbox.cpp +++ b/tests/auto/qgroupbox/tst_qgroupbox.cpp @@ -80,6 +80,7 @@ private slots: void clicked(); void toggledVsClicked(); void childrenAreDisabled(); + void propagateFocus(); private: bool checked; @@ -459,5 +460,15 @@ void tst_QGroupBox::childrenAreDisabled() } } +void tst_QGroupBox::propagateFocus() +{ + QGroupBox box; + QLineEdit lineEdit(&box); + box.show(); + box.setFocus(); + QTest::qWait(250); + QCOMPARE(qApp->focusWidget(), &lineEdit); +} + QTEST_MAIN(tst_QGroupBox) #include "tst_qgroupbox.moc" -- cgit v0.12 From bb8e25a5074a378d5003577fefbeabb1de846a81 Mon Sep 17 00:00:00 2001 From: Rohan McGovern Date: Wed, 1 Jul 2009 10:29:09 +1000 Subject: Fixes configure.exe silently disabling cetest even if you asked for it when paths to the ActiveSync headers/libraries are not set up. Reviewed-by: Michael Goddard --- tools/configure/configureapp.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index 8780c62..597cd0e 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -604,10 +604,13 @@ void Configure::parseCmdLine() // cetest --------------------------------------------------- else if (configCmdLine.at(i) == "-no-cetest") { dictionary[ "CETEST" ] = "no"; + dictionary[ "CETEST_REQUESTED" ] = "no"; } else if (configCmdLine.at(i) == "-cetest") { // although specified to use it, we stay at "auto" state // this is because checkAvailability() adds variables - // we need for crosscompilation + // we need for crosscompilation; but remember if we asked + // for it. + dictionary[ "CETEST_REQUESTED" ] = "yes"; } // Qt/CE - signing tool ------------------------------------- else if( configCmdLine.at(i) == "-signature") { @@ -1824,6 +1827,11 @@ bool Configure::checkAvailability(const QString &part) dictionary[ "QT_CE_RAPI_INC" ] += QLatin1String("\"") + rapiHeader + QLatin1String("\""); dictionary[ "QT_CE_RAPI_LIB" ] += QLatin1String("\"") + rapiLib + QLatin1String("\""); } + else if (dictionary[ "CETEST_REQUESTED" ] == "yes") { + cout << "cetest could not be enabled: rapi.h and rapi.lib could not be found." << endl; + cout << "Make sure the environment is set up for compiling with ActiveSync." << endl; + dictionary[ "DONE" ] = "error"; + } } else if (part == "INCREDIBUILD_XGE") available = findFile("BuildConsole.exe") && findFile("xgConsole.exe"); -- cgit v0.12 From c5b5cd3d704bf7c84634188d44c5208fbe55e25b Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Wed, 1 Jul 2009 12:00:16 +1000 Subject: OpenVG compile fix - use const_cast instead of static_cast Reviewed-by: trustme --- src/openvg/qpaintengine_vg.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp index 37945bf..c7fe604 100644 --- a/src/openvg/qpaintengine_vg.cpp +++ b/src/openvg/qpaintengine_vg.cpp @@ -1320,11 +1320,11 @@ QPainterState *QVGPaintEngine::createState(QPainterState *orig) const if (!orig) { return new QVGPainterState(); } else { - QVGPaintEnginePrivate *d = - static_cast(d_ptr); + Q_D(const QVGPaintEngine); + QVGPaintEnginePrivate *d2 = const_cast(d); QVGPainterState *origState = static_cast(orig); - origState->savedDirty = d->dirty; - d->dirty = 0; + origState->savedDirty = d2->dirty; + d2->dirty = 0; return new QVGPainterState(*origState); } } -- cgit v0.12 From 9cb231d773db6deb8fb145eb40aa949a2758d002 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Wed, 1 Jul 2009 10:22:15 +0200 Subject: ItemViews: Fixed signal entered not being emitted when using the mouse wheel The solution is to check the the current "entered item" hasn't change also when the scrollbars change values Task-number: 200665 Reviewed-by: janarve --- src/gui/itemviews/qabstractitemview.cpp | 72 ++++++++++++---------- src/gui/itemviews/qabstractitemview_p.h | 3 + .../qabstractitemview/tst_qabstractitemview.cpp | 19 ++++++ 3 files changed, 61 insertions(+), 33 deletions(-) diff --git a/src/gui/itemviews/qabstractitemview.cpp b/src/gui/itemviews/qabstractitemview.cpp index cb0037b..b64bc71 100644 --- a/src/gui/itemviews/qabstractitemview.cpp +++ b/src/gui/itemviews/qabstractitemview.cpp @@ -127,6 +127,37 @@ void QAbstractItemViewPrivate::init() q->setAttribute(Qt::WA_InputMethodEnabled); } +void QAbstractItemViewPrivate::checkMouseMove(const QPersistentModelIndex &index) +{ + //we take a persistent model index because the model might change by emitting signals + Q_Q(QAbstractItemView); + if (viewportEnteredNeeded || enteredIndex != index) { + viewportEnteredNeeded = false; + + if (index.isValid()) { + emit q->entered(index); +#ifndef QT_NO_STATUSTIP + QString statustip = model->data(index, Qt::StatusTipRole).toString(); + if (parent && !statustip.isEmpty()) { + QStatusTipEvent tip(statustip); + QApplication::sendEvent(parent, &tip); + } +#endif + } else { +#ifndef QT_NO_STATUSTIP + if (parent) { + QString emptyString; + QStatusTipEvent tip( emptyString ); + QApplication::sendEvent(parent, &tip); + } +#endif + emit q->viewportEntered(); + } + enteredIndex = index; + } +} + + /*! \class QAbstractItemView @@ -1557,7 +1588,7 @@ void QAbstractItemView::mouseMoveEvent(QMouseEvent *event) } #endif // QT_NO_DRAGANDDROP - QModelIndex index = indexAt(bottomRight); + QPersistentModelIndex index = indexAt(bottomRight); QModelIndex buddy = d->model->buddy(d->pressedIndex); if ((state() == EditingState && d->hasEditor(buddy)) || edit(index, NoEditTriggers, event)) @@ -1568,33 +1599,7 @@ void QAbstractItemView::mouseMoveEvent(QMouseEvent *event) else topLeft = bottomRight; - if (d->viewportEnteredNeeded || d->enteredIndex != index) { - d->viewportEnteredNeeded = false; - - // signal handlers may change the model - QPersistentModelIndex persistent = index; - if (persistent.isValid()) { - emit entered(persistent); -#ifndef QT_NO_STATUSTIP - QString statustip = d->model->data(persistent, Qt::StatusTipRole).toString(); - if (parent() && !statustip.isEmpty()) { - QStatusTipEvent tip(statustip); - QApplication::sendEvent(parent(), &tip); - } -#endif - } else { -#ifndef QT_NO_STATUSTIP - if (parent()) { - QString emptyString; - QStatusTipEvent tip(emptyString); - QApplication::sendEvent(parent(), &tip); - } -#endif - emit viewportEntered(); - } - d->enteredIndex = persistent; - index = persistent; - } + d->checkMouseMove(index); #ifndef QT_NO_DRAGANDDROP if (index.isValid() @@ -1613,14 +1618,13 @@ void QAbstractItemView::mouseMoveEvent(QMouseEvent *event) // Do the normalize ourselves, since QRect::normalized() is flawed QRect selectionRect = QRect(topLeft, bottomRight); - QPersistentModelIndex persistent = index; setSelection(selectionRect, command); // set at the end because it might scroll the view - if (persistent.isValid() - && (persistent != d->selectionModel->currentIndex()) - && d->isIndexEnabled(persistent)) - d->selectionModel->setCurrentIndex(persistent, QItemSelectionModel::NoUpdate); + if (index.isValid() + && (index != d->selectionModel->currentIndex()) + && d->isIndexEnabled(index)) + d->selectionModel->setCurrentIndex(index, QItemSelectionModel::NoUpdate); } } @@ -2422,6 +2426,7 @@ void QAbstractItemView::verticalScrollbarValueChanged(int value) Q_D(QAbstractItemView); if (verticalScrollBar()->maximum() == value && d->model->canFetchMore(d->root)) d->model->fetchMore(d->root); + d->checkMouseMove(viewport()->mapFromGlobal(QCursor::pos())); } /*! @@ -2432,6 +2437,7 @@ void QAbstractItemView::horizontalScrollbarValueChanged(int value) Q_D(QAbstractItemView); if (horizontalScrollBar()->maximum() == value && d->model->canFetchMore(d->root)) d->model->fetchMore(d->root); + d->checkMouseMove(viewport()->mapFromGlobal(QCursor::pos())); } /*! diff --git a/src/gui/itemviews/qabstractitemview_p.h b/src/gui/itemviews/qabstractitemview_p.h index 030147b..c2c1f32 100644 --- a/src/gui/itemviews/qabstractitemview_p.h +++ b/src/gui/itemviews/qabstractitemview_p.h @@ -139,6 +139,9 @@ public: const QEvent *event) const; virtual void selectAll(QItemSelectionModel::SelectionFlags command); + void checkMouseMove(const QPersistentModelIndex &index); + inline void checkMouseMove(const QPoint &pos) { checkMouseMove(q_func()->indexAt(pos)); } + inline QItemSelectionModel::SelectionFlags selectionBehaviorFlags() const { switch (selectionBehavior) { diff --git a/tests/auto/qabstractitemview/tst_qabstractitemview.cpp b/tests/auto/qabstractitemview/tst_qabstractitemview.cpp index c117aa4..0bc459e 100644 --- a/tests/auto/qabstractitemview/tst_qabstractitemview.cpp +++ b/tests/auto/qabstractitemview/tst_qabstractitemview.cpp @@ -212,6 +212,7 @@ private slots: void task221955_selectedEditor(); void task250754_fontChange(); + void task200665_itemEntered(); }; class MyAbstractItemDelegate : public QAbstractItemDelegate @@ -1199,5 +1200,23 @@ void tst_QAbstractItemView::task250754_fontChange() qApp->setStyleSheet(app_css); } +void tst_QAbstractItemView::task200665_itemEntered() +{ + //we test that view will emit entered + //when the scrollbar move but not the mouse itself + QStandardItemModel model(1000,1); + QListView view; + view.setModel(&model); + view.show(); + QTest::qWait(200); + QRect rect = view.visualRect(model.index(0,0)); + QCursor::setPos( view.viewport()->mapToGlobal(rect.center()) ); + QSignalSpy spy(&view, SIGNAL(entered(QModelIndex))); + view.verticalScrollBar()->setValue(view.verticalScrollBar()->maximum()); + QCOMPARE(spy.count(), 1); + +} + + QTEST_MAIN(tst_QAbstractItemView) #include "tst_qabstractitemview.moc" -- cgit v0.12 From 728430d16fd62de001ba8eaccabae41feef790f2 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Wed, 1 Jul 2009 10:38:51 +0200 Subject: Added QGraphicsScene::sendEvent(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Merge-request: 787 Reviewed-by: Bjørn Erik Nilsen --- src/gui/graphicsview/qgraphicsscene.cpp | 28 +++++++++++++++++++++++ src/gui/graphicsview/qgraphicsscene.h | 2 ++ tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp | 29 +++++++++++++++++++++++- 3 files changed, 58 insertions(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 0dc77cc..d790640 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5988,6 +5988,34 @@ void QGraphicsScene::setActiveWindow(QGraphicsWidget *widget) } } +/*! + \since 4.6 + + Sends event \a event to item \a item through possible event filters. + + The event is sent only if the item is enabled. + + Returns \c false if the event was filtered or if the item is disabled. + Otherwise returns the value that was returned from the event handler. + + \sa QGraphicsItem::sceneEvent(), QGraphicsItem::sceneEventFilter() +*/ +bool QGraphicsScene::sendEvent(QGraphicsItem *item, QEvent *event) +{ + Q_D(QGraphicsScene); + if (!item) { + qWarning("QGraphicsScene::sendEvent: cannot send event to a null item"); + return false; + } + if (item->scene() != this) { + qWarning("QGraphicsScene::sendEvent: item %p's scene (%p)" + " is different from this scene (%p)", + item, item->scene(), this); + return false; + } + return d->sendEvent(item, event); +} + void QGraphicsScenePrivate::addView(QGraphicsView *view) { views << view; diff --git a/src/gui/graphicsview/qgraphicsscene.h b/src/gui/graphicsview/qgraphicsscene.h index 4d65b91..c8b147f 100644 --- a/src/gui/graphicsview/qgraphicsscene.h +++ b/src/gui/graphicsview/qgraphicsscene.h @@ -229,6 +229,8 @@ public: QGraphicsWidget *activeWindow() const; void setActiveWindow(QGraphicsWidget *widget); + bool sendEvent(QGraphicsItem *item, QEvent *event); + public Q_SLOTS: void update(const QRectF &rect = QRectF()); void invalidate(const QRectF &rect = QRectF(), SceneLayers layers = AllLayers); diff --git a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp index 6439125..4247cca 100644 --- a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp +++ b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp @@ -141,7 +141,7 @@ protected: } }; -class EventSpy : public QObject +class EventSpy : public QGraphicsWidget { Q_OBJECT public: @@ -151,6 +151,13 @@ public: watched->installEventFilter(this); } + EventSpy(QGraphicsScene *scene, QGraphicsItem *watched, QEvent::Type type) + : _count(0), spied(type) + { + scene->addItem(this); + watched->installSceneEventFilter(this); + } + int count() const { return _count; } protected: @@ -162,6 +169,14 @@ protected: return false; } + bool sceneEventFilter(QGraphicsItem *watched, QEvent *event) + { + Q_UNUSED(watched); + if (event->type() == spied) + ++_count; + return false; + } + int _count; QEvent::Type spied; }; @@ -236,6 +251,7 @@ private slots: void changedSignal(); void stickyFocus_data(); void stickyFocus(); + void sendEvent(); // task specific tests below me void task139710_bspTreeCrash(); @@ -3587,5 +3603,16 @@ void tst_QGraphicsScene::stickyFocus() QCOMPARE(text->hasFocus(), sticky); } +void tst_QGraphicsScene::sendEvent() +{ + QGraphicsScene scene; + QGraphicsTextItem *item = scene.addText(QString()); + EventSpy *spy = new EventSpy(&scene, item, QEvent::User); + QCOMPARE(spy->count(), 0); + QEvent event(QEvent::User); + scene.sendEvent(item, &event); + QCOMPARE(spy->count(), 1); +} + QTEST_MAIN(tst_QGraphicsScene) #include "tst_qgraphicsscene.moc" -- cgit v0.12 From f1d54091ec24e6cf57008f9b4fac7ddf7c7c8de3 Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Wed, 1 Jul 2009 11:49:29 +0200 Subject: doc: Fixed several qdoc error reports. Also changed qdoc not to warn about undocumented parameters if the function is marked with the \reimp command. --- src/gui/kernel/qgesture.cpp | 16 +++++ src/gui/styles/qwindowsvistastyle.cpp | 127 ++++++++++++++++------------------ tools/qdoc3/generator.cpp | 2 +- 3 files changed, 78 insertions(+), 67 deletions(-) diff --git a/src/gui/kernel/qgesture.cpp b/src/gui/kernel/qgesture.cpp index d7b2d1b..ff369e2 100644 --- a/src/gui/kernel/qgesture.cpp +++ b/src/gui/kernel/qgesture.cpp @@ -266,6 +266,22 @@ void QGesture::setPos(const QPoint &point) d_func()->pos = point; } +/*! \fn void QGesture::setAccepted(bool accepted) + Marks the gesture with the value of \a accepted. + */ + +/*! \fn bool QGesture::isAccepted() const + Returns true if the gesture is marked accepted. + */ + +/*! \fn void QGesture::accept() + Marks the gesture accepted. +*/ + +/*! \fn void QGesture::ignore() + Marks the gesture ignored. +*/ + /*! \class QPanningGesture \since 4.6 diff --git a/src/gui/styles/qwindowsvistastyle.cpp b/src/gui/styles/qwindowsvistastyle.cpp index 5f0f053..b131d39 100644 --- a/src/gui/styles/qwindowsvistastyle.cpp +++ b/src/gui/styles/qwindowsvistastyle.cpp @@ -196,17 +196,15 @@ void Animation::paint(QPainter *painter, const QStyleOption *option) Q_UNUSED(painter); } -/* -* ! \internal -* -* Helperfunction to paint the current transition state -* between two animation frames. -* -* The result is a blended image consisting of -* ((alpha)*_primaryImage) + ((1-alpha)*_secondaryImage) -* -*/ +/*! \internal + + Helperfunction to paint the current transition state between two + animation frames. + The result is a blended image consisting of ((alpha)*_primaryImage) + + ((1-alpha)*_secondaryImage) + +*/ void Animation::drawBlendedImage(QPainter *painter, QRect rect, float alpha) { if (_secondaryImage.isNull() || _primaryImage.isNull()) return; @@ -248,14 +246,11 @@ void Animation::drawBlendedImage(QPainter *painter, QRect rect, float alpha) { painter->drawImage(rect, _tempImage); } -/* -* ! \internal -* -* Paints a transition state. The result will be a mix between the -* initial and final state of the transition, depending on the -* time difference between _startTime and current time. +/*! \internal + Paints a transition state. The result will be a mix between the + initial and final state of the transition, depending on the time + difference between _startTime and current time. */ - void Transition::paint(QPainter *painter, const QStyleOption *option) { float alpha = 1.0; @@ -278,15 +273,11 @@ void Transition::paint(QPainter *painter, const QStyleOption *option) drawBlendedImage(painter, option->rect, alpha); } -/* -* ! \internal -* -* Paints a pulse. The result will be a mix between the -* primary and secondary pulse images depending on the -* time difference between _startTime and current time. +/*! \internal + Paints a pulse. The result will be a mix between the primary and + secondary pulse images depending on the time difference between + _startTime and current time. */ - - void Pulse::paint(QPainter *painter, const QStyleOption *option) { float alpha = 1.0; @@ -308,31 +299,37 @@ void Pulse::paint(QPainter *painter, const QStyleOption *option) /*! - \reimp - * - * Animations are used for some state transitions on specific widgets. - * - * Only one running animation can exist for a widget at any specific time. - * Animations can be added through QWindowsVistaStylePrivate::startAnimation(Animation *) - * and any existing animation on a widget can be retrieved with - * QWindowsVistaStylePrivate::widgetAnimation(Widget *). - * - * Once an animation has been started, QWindowsVistaStylePrivate::timerEvent(QTimerEvent *) - * will continuously call update() on the widget until it is stopped, meaning that drawPrimitive - * will be called many times until the transition has completed. During this time, the result - * will be retrieved by the Animation::paint(...) function and not by the style itself. - * - * To determine if a transition should occur, the style needs to know the previous state of the - * widget as well as the current one. This is solved by updating dynamic properties on the widget - * every time the function is called. - * - * Transitions interrupting existing transitions should always be smooth, so whenever a hover-transition - * is started on a pulsating button, it uses the current frame of the pulse-animation as the - * starting image for the hover transition. - * + \internal + + Animations are used for some state transitions on specific widgets. + + Only one running animation can exist for a widget at any specific + time. Animations can be added through + QWindowsVistaStylePrivate::startAnimation(Animation *) and any + existing animation on a widget can be retrieved with + QWindowsVistaStylePrivate::widgetAnimation(Widget *). + + Once an animation has been started, + QWindowsVistaStylePrivate::timerEvent(QTimerEvent *) will + continuously call update() on the widget until it is stopped, + meaning that drawPrimitive will be called many times until the + transition has completed. During this time, the result will be + retrieved by the Animation::paint(...) function and not by the style + itself. + + To determine if a transition should occur, the style needs to know + the previous state of the widget as well as the current one. This is + solved by updating dynamic properties on the widget every time the + function is called. + + Transitions interrupting existing transitions should always be + smooth, so whenever a hover-transition is started on a pulsating + button, it uses the current frame of the pulse-animation as the + starting image for the hover transition. + */ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option, - QPainter *painter, const QWidget *widget) const + QPainter *painter, const QWidget *widget) const { QWindowsVistaStylePrivate *d = const_cast(d_func()); @@ -877,11 +874,9 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt /*! - - \reimp + \internal see drawPrimitive for comments on the animation support - */ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const @@ -1541,7 +1536,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption } /*! - \reimp + \internal see drawPrimitive for comments on the animation support @@ -1927,7 +1922,7 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle } /*! - \reimp + \internal */ QSize QWindowsVistaStyle::sizeFromContents(ContentsType type, const QStyleOption *option, const QSize &size, const QWidget *widget) const @@ -2004,7 +1999,7 @@ QSize QWindowsVistaStyle::sizeFromContents(ContentsType type, const QStyleOption } /*! - \reimp + \internal */ QRect QWindowsVistaStyle::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const { @@ -2175,7 +2170,7 @@ static bool buttonVisible(const QStyle::SubControl sc, const QStyleOptionTitleBa } -/*! \reimp */ +/*! \internal */ int QWindowsVistaStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget, QStyleHintReturn *returnData) const { @@ -2209,7 +2204,7 @@ int QWindowsVistaStyle::styleHint(StyleHint hint, const QStyleOption *option, co /*! - \reimp + \internal */ QRect QWindowsVistaStyle::subControlRect(ComplexControl control, const QStyleOptionComplex *option, SubControl subControl, const QWidget *widget) const @@ -2318,7 +2313,7 @@ QRect QWindowsVistaStyle::subControlRect(ComplexControl control, const QStyleOpt } /*! - \reimp + \internal */ bool QWindowsVistaStyle::event(QEvent *e) { @@ -2341,7 +2336,7 @@ bool QWindowsVistaStyle::event(QEvent *e) } /*! - \reimp + \internal */ QStyle::SubControl QWindowsVistaStyle::hitTestComplexControl(ComplexControl control, const QStyleOptionComplex *option, const QPoint &pos, const QWidget *widget) const @@ -2353,7 +2348,7 @@ QStyle::SubControl QWindowsVistaStyle::hitTestComplexControl(ComplexControl cont } /*! - \reimp + \internal */ int QWindowsVistaStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const { @@ -2378,7 +2373,7 @@ int QWindowsVistaStyle::pixelMetric(PixelMetric metric, const QStyleOption *opti } /*! - \reimp + \internal */ QPalette QWindowsVistaStyle::standardPalette() const { @@ -2386,7 +2381,7 @@ QPalette QWindowsVistaStyle::standardPalette() const } /*! - \reimp + \internal */ void QWindowsVistaStyle::polish(QApplication *app) { @@ -2394,7 +2389,7 @@ void QWindowsVistaStyle::polish(QApplication *app) } /*! - \reimp + \internal */ void QWindowsVistaStyle::polish(QWidget *widget) { @@ -2448,7 +2443,7 @@ void QWindowsVistaStyle::polish(QWidget *widget) } /*! - \reimp + \internal */ void QWindowsVistaStyle::unpolish(QWidget *widget) { @@ -2490,7 +2485,7 @@ void QWindowsVistaStyle::unpolish(QWidget *widget) /*! - \reimp + \internal */ void QWindowsVistaStyle::unpolish(QApplication *app) { @@ -2498,7 +2493,7 @@ void QWindowsVistaStyle::unpolish(QApplication *app) } /*! - \reimp + \internal */ void QWindowsVistaStyle::polish(QPalette &pal) { @@ -2507,7 +2502,7 @@ void QWindowsVistaStyle::polish(QPalette &pal) } /*! - \reimp + \internal */ QPixmap QWindowsVistaStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *option, const QWidget *widget) const diff --git a/tools/qdoc3/generator.cpp b/tools/qdoc3/generator.cpp index 7e10f3e..00831d1 100644 --- a/tools/qdoc3/generator.cpp +++ b/tools/qdoc3/generator.cpp @@ -401,7 +401,7 @@ void Generator::generateBody(const Node *node, CodeMarker *marker) } } } - if (needWarning) + if (needWarning && !func->isReimp()) node->doc().location().warning( tr("Undocumented parameter '%1' in %2").arg(*a).arg(marker->plainFullName(node))); } -- cgit v0.12 From adc1c08ed9a5de2263564ba654a8ef7fed54af82 Mon Sep 17 00:00:00 2001 From: miniak Date: Wed, 1 Jul 2009 11:49:45 +0200 Subject: src/winmain: Remove QT_WA and non-Unicode code paths, dropping Win9x and NT support Also TCHAR -> wchar_t LPTSTR/LPCTSTRs -> LPWSTR/LPCWSTRs Merge-request: 604 Reviewed-by: Marius Storm-Olsen --- src/winmain/qtmain_win.cpp | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/winmain/qtmain_win.cpp b/src/winmain/qtmain_win.cpp index c266cbf..5f929d6 100644 --- a/src/winmain/qtmain_win.cpp +++ b/src/winmain/qtmain_win.cpp @@ -89,18 +89,12 @@ extern "C" int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR /*cmdParamarg*/, int cmdShow) #endif { - QByteArray cmdParam; - QT_WA({ - LPTSTR cmdline = GetCommandLineW(); - cmdParam = QString::fromUtf16((const unsigned short *)cmdline).toLocal8Bit(); - }, { - cmdParam = GetCommandLineA(); - }); + QByteArray cmdParam = QString::fromWCharArray(GetCommandLine()).toLocal8Bit(); #if defined(Q_OS_WINCE) - TCHAR appName[256]; - GetModuleFileName(0, appName, 255); - cmdParam.prepend(QString::fromLatin1("\"%1\" ").arg(QString::fromUtf16((const unsigned short *)appName)).toLocal8Bit()); + wchar_t appName[MAX_PATH]; + GetModuleFileName(0, appName, MAX_PATH); + cmdParam.prepend(QString(QLatin1String("\"%1\" ")).arg(QString::fromWCharArray(appName)).toLocal8Bit()); #endif int argc = 0; @@ -108,9 +102,9 @@ int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR /*cmdPara qWinMain(instance, prevInstance, cmdParam.data(), cmdShow, argc, argv); #if defined(Q_OS_WINCE) - TCHAR uniqueAppID[256]; - GetModuleFileName(0, uniqueAppID, 255); - QString uid = QString::fromUtf16((const unsigned short *)uniqueAppID).toLower().replace(QLatin1Char('\\'), QLatin1Char('_')); + wchar_t uniqueAppID[MAX_PATH]; + GetModuleFileName(0, uniqueAppID, MAX_PATH); + QString uid = QString::fromWCharArray(uniqueAppID).toLower().replace(QLatin1String("\\"), QLatin1String("_")); // If there exists an other instance of this application // it will be the owner of a mutex with the unique ID. -- cgit v0.12 From 5ae330b6546dabada53c394b53ce9513f552a8a5 Mon Sep 17 00:00:00 2001 From: miniak Date: Wed, 1 Jul 2009 11:49:48 +0200 Subject: src/corelib: Remove QT_WA and non-Unicode code paths, dropping Win9x and NT support Also: QString::fromUtf16() -> QString::fromWCharArray() WCHAR & TCHAR -> wchar_t LPTSTR/LPCTSTR -> LPWSTR/LPCWSTR Documentation update Merge-request: 604 Reviewed-by: Marius Storm-Olsen --- src/corelib/codecs/qtextcodec.cpp | 14 +- src/corelib/global/qglobal.cpp | 43 +- src/corelib/global/qglobal.h | 4 +- src/corelib/io/qfileinfo.cpp | 6 +- src/corelib/io/qfilesystemwatcher_win.cpp | 12 +- src/corelib/io/qfsfileengine_iterator_win.cpp | 32 +- src/corelib/io/qfsfileengine_p.h | 4 +- src/corelib/io/qfsfileengine_win.cpp | 798 +++++++++----------------- src/corelib/io/qprocess_win.cpp | 231 +++----- src/corelib/io/qsettings.cpp | 37 +- src/corelib/io/qsettings_win.cpp | 209 ++----- src/corelib/kernel/qcoreapplication.cpp | 22 +- src/corelib/kernel/qcoreapplication_win.cpp | 66 +-- src/corelib/kernel/qcorecmdlineargs_p.h | 9 +- src/corelib/kernel/qeventdispatcher_win.cpp | 89 ++- src/corelib/kernel/qfunctions_wince.cpp | 12 +- src/corelib/kernel/qfunctions_wince.h | 6 +- src/corelib/kernel/qsharedmemory_win.cpp | 17 +- src/corelib/kernel/qsystemsemaphore_win.cpp | 6 +- src/corelib/kernel/qtimer.cpp | 5 +- src/corelib/plugin/qlibrary.cpp | 8 +- src/corelib/plugin/qlibrary_win.cpp | 34 +- src/corelib/thread/qmutex_win.cpp | 14 +- src/corelib/thread/qthread_win.cpp | 38 +- src/corelib/thread/qwaitcondition_win.cpp | 6 +- src/corelib/tools/qdatetime.cpp | 13 +- src/corelib/tools/qlocale.cpp | 133 ++--- src/corelib/tools/qstring.cpp | 26 +- 28 files changed, 554 insertions(+), 1340 deletions(-) diff --git a/src/corelib/codecs/qtextcodec.cpp b/src/corelib/codecs/qtextcodec.cpp index d4e5d44..c4266a0 100644 --- a/src/corelib/codecs/qtextcodec.cpp +++ b/src/corelib/codecs/qtextcodec.cpp @@ -233,9 +233,9 @@ QString QWindowsLocalCodec::convertToUnicode(const char *chars, int length, Conv return QString(); const int wclen_auto = 4096; - WCHAR wc_auto[wclen_auto]; + wchar_t wc_auto[wclen_auto]; int wclen = wclen_auto; - WCHAR *wc = wc_auto; + wchar_t *wc = wc_auto; int len; QString sp; bool prepend = false; @@ -275,7 +275,7 @@ QString QWindowsLocalCodec::convertToUnicode(const char *chars, int length, Conv } else { wclen = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, mb, mblen, 0, 0); - wc = new WCHAR[wclen]; + wc = new wchar_t[wclen]; // and try again... } } else if (r == ERROR_NO_UNICODE_TRANSLATION) { @@ -341,7 +341,7 @@ QString QWindowsLocalCodec::convertToUnicodeCharByChar(const char *chars, int le const char *next = 0; QString s; while((next = CharNextExA(CP_ACP, mb, 0)) != mb) { - WCHAR wc[2] ={0}; + wchar_t wc[2] ={0}; int charlength = next - mb; int len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED|MB_ERR_INVALID_CHARS, mb, charlength, wc, 2); if (len>0) { @@ -1042,16 +1042,10 @@ QList QTextCodec::availableMibs() This might be needed for some applications that want to use their own mechanism for setting the locale. - Setting this codec is not supported on DOS based Windows. - \sa codecForLocale() */ void QTextCodec::setCodecForLocale(QTextCodec *c) { -#ifdef Q_WS_WIN - if (QSysInfo::WindowsVersion& QSysInfo::WV_DOS_based) - return; -#endif localeMapper = c; if (!localeMapper) setupLocaleMapper(); diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index bb639fe..f7a97e1 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -915,7 +915,7 @@ QT_BEGIN_NAMESPACE \fn bool qt_winUnicode() \relates - Use QSysInfo::WindowsVersion and QSysInfo::WV_DOS_based instead. + This function always returns true. \sa QSysInfo */ @@ -1620,15 +1620,11 @@ QSysInfo::WinVersion QSysInfo::windowsVersion() if (winver) return winver; winver = QSysInfo::WV_NT; -#ifndef Q_OS_WINCE - OSVERSIONINFOA osver; - osver.dwOSVersionInfoSize = sizeof(osver); - GetVersionExA(&osver); -#else - DWORD qt_cever = 0; OSVERSIONINFOW osver; osver.dwOSVersionInfoSize = sizeof(osver); GetVersionEx(&osver); +#ifdef Q_OS_WINCE + DWORD qt_cever = 0; qt_cever = osver.dwMajorVersion * 100; qt_cever += osver.dwMinorVersion * 10; #endif @@ -1904,29 +1900,16 @@ QString qt_error_string(int errorCode) break; default: { #ifdef Q_OS_WIN - QT_WA({ - unsigned short *string = 0; - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, - NULL, - errorCode, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR)&string, - 0, - NULL); - ret = QString::fromUtf16(string); - LocalFree((HLOCAL)string); - }, { - char *string = 0; - FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, - NULL, - errorCode, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPSTR)&string, - 0, - NULL); - ret = QString::fromLocal8Bit(string); - LocalFree((HLOCAL)string); - }); + wchar_t *string = 0; + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + errorCode, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + string, + 0, + NULL); + ret = QString::fromWCharArray(string); + LocalFree((HLOCAL)string); if (ret.isEmpty() && errorCode == ERROR_MOD_NOT_FOUND) ret = QString::fromLatin1("The specified module could not be found."); diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index afc3f58..00a9466 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -147,7 +147,7 @@ namespace QT_NAMESPACE {} MSDOS - MS-DOS and Windows OS2 - OS/2 OS2EMX - XFree86 on OS/2 (not PM) - WIN32 - Win32 (Windows 95/98/ME and Windows NT/2000/XP) + WIN32 - Win32 (Windows 2000/XP/Vista/7 and Windows Server 2003/2008) WINCE - WinCE (Windows CE 5.0) CYGWIN - Cygwin SOLARIS - Sun Solaris @@ -1416,7 +1416,7 @@ inline QT3_SUPPORT bool qSysInfo(int *wordSize, bool *bigEndian) #if defined(Q_WS_WIN) || defined(Q_OS_CYGWIN) #if defined(QT3_SUPPORT) -inline QT3_SUPPORT bool qt_winUnicode() { return !(QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based); } +inline QT3_SUPPORT bool qt_winUnicode() { return true; } inline QT3_SUPPORT int qWinVersion() { return QSysInfo::WindowsVersion; } #endif diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp index 4c1c21a..c50bb51 100644 --- a/src/corelib/io/qfileinfo.cpp +++ b/src/corelib/io/qfileinfo.cpp @@ -117,11 +117,7 @@ bool QFileInfoPrivate::hasAccess(Access access) const if (access == ExecuteAccess) return getFileFlags(QAbstractFileEngine::ExeUserPerm); - QT_WA( { - return ::_waccess((TCHAR *)QFSFileEnginePrivate::longFileName(data->fileName).utf16(), mode) == 0; - } , { - return QT_ACCESS(QFSFileEnginePrivate::win95Name(data->fileName), mode) == 0; - } ); + return ::_waccess((wchar_t*)QFSFileEnginePrivate::longFileName(data->fileName).utf16(), mode) == 0; #endif return false; } diff --git a/src/corelib/io/qfilesystemwatcher_win.cpp b/src/corelib/io/qfilesystemwatcher_win.cpp index 9a3aeae..c15b1d2 100644 --- a/src/corelib/io/qfilesystemwatcher_win.cpp +++ b/src/corelib/io/qfilesystemwatcher_win.cpp @@ -56,9 +56,7 @@ QT_BEGIN_NAMESPACE QWindowsFileSystemWatcherEngine::QWindowsFileSystemWatcherEngine() : msg(0) { - HANDLE h = QT_WA_INLINE(CreateEventW(0, false, false, 0), - CreateEventA(0, false, false, 0)); - if (h != INVALID_HANDLE_VALUE) { + if (HANDLE h = CreateEvent(0, false, false, 0)) { handles.reserve(MAXIMUM_WAIT_OBJECTS); handles.append(h); } @@ -216,13 +214,7 @@ QStringList QWindowsFileSystemWatcherEngine::addPaths(const QStringList &paths, const QString effectiveAbsolutePath = isDir ? (absolutePath + QLatin1Char('/')) : absolutePath; - QT_WA({ - handle.handle = FindFirstChangeNotificationW((TCHAR *) QDir::toNativeSeparators(effectiveAbsolutePath).utf16(), - false, flags); - },{ - handle.handle = FindFirstChangeNotificationA(QDir::toNativeSeparators(effectiveAbsolutePath).toLocal8Bit(), - false, flags); - }) + handle.handle = FindFirstChangeNotification((wchar_t*) QDir::toNativeSeparators(effectiveAbsolutePath).utf16(), false, flags); handle.flags = flags; if (handle.handle == INVALID_HANDLE_VALUE) continue; diff --git a/src/corelib/io/qfsfileengine_iterator_win.cpp b/src/corelib/io/qfsfileengine_iterator_win.cpp index 2336542..dd4ddf3 100644 --- a/src/corelib/io/qfsfileengine_iterator_win.cpp +++ b/src/corelib/io/qfsfileengine_iterator_win.cpp @@ -79,11 +79,7 @@ void QFSFileEngineIteratorPlatformSpecificData::saveCurrentFileName() it->currentEntry = uncShares.at(uncShareIndex - 1); } else { // Local directory - QT_WA({ - it->currentEntry = QString::fromUtf16((unsigned short *)findData.cFileName); - } , { - it->currentEntry = QString::fromLocal8Bit((const char *)findData.cFileName); - }); + it->currentEntry = QString::fromWCharArray(findData.cFileName); } } @@ -97,17 +93,10 @@ void QFSFileEngineIterator::advance() if (platform->uncFallback) { ++platform->uncShareIndex; } else if (platform->findFileHandle != INVALID_HANDLE_VALUE) { - QT_WA({ - if (!FindNextFile(platform->findFileHandle, &platform->findData)) { - platform->done = true; - FindClose(platform->findFileHandle); - } - } , { - if (!FindNextFileA(platform->findFileHandle, (WIN32_FIND_DATAA *)&platform->findData)) { - platform->done = true; - FindClose(platform->findFileHandle); - } - }); + if (!FindNextFile(platform->findFileHandle, &platform->findData)) { + platform->done = true; + FindClose(platform->findFileHandle); + } } } @@ -141,15 +130,8 @@ bool QFSFileEngineIterator::hasNext() const path.append(QLatin1Char('/')); path.append(QLatin1String("*.*")); - QT_WA({ - QString fileName = QFSFileEnginePrivate::longFileName(path); - platform->findFileHandle = FindFirstFileW((TCHAR *)fileName.utf16(), - &platform->findData); - }, { - // Cast is safe, since char is at end of WIN32_FIND_DATA - platform->findFileHandle = FindFirstFileA(QFSFileEnginePrivate::win95Name(path), - (WIN32_FIND_DATAA*)&platform->findData); - }); + QString fileName = QFSFileEnginePrivate::longFileName(path); + platform->findFileHandle = FindFirstFile((const wchar_t *)fileName.utf16(), &platform->findData); if (platform->findFileHandle == INVALID_HANDLE_VALUE) { if (path.startsWith(QLatin1String("//"))) { diff --git a/src/corelib/io/qfsfileengine_p.h b/src/corelib/io/qfsfileengine_p.h index 5aef229..864599f 100644 --- a/src/corelib/io/qfsfileengine_p.h +++ b/src/corelib/io/qfsfileengine_p.h @@ -72,7 +72,6 @@ class QFSFileEnginePrivate : public QAbstractFileEnginePrivate public: #ifdef Q_WS_WIN - static QByteArray win95Name(const QString &path); static QString longFileName(const QString &path); #endif static QString canonicalized(const QString &path); @@ -151,8 +150,7 @@ public: #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) static void resolveLibs(); - static bool resolveUNCLibs_NT(); - static bool resolveUNCLibs_9x(); + static bool resolveUNCLibs(); static bool uncListSharesOnServer(const QString &server, QStringList *list); #endif diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp index eef39e4..ee49853 100644 --- a/src/corelib/io/qfsfileengine_win.cpp +++ b/src/corelib/io/qfsfileengine_win.cpp @@ -152,66 +152,64 @@ void QFSFileEnginePrivate::resolveLibs() triedResolve = true; #if !defined(Q_OS_WINCE) - if(QSysInfo::WindowsVersion & QSysInfo::WV_NT_based) { - HINSTANCE advapiHnd = LoadLibraryW(L"advapi32"); - if (advapiHnd) { - ptrGetNamedSecurityInfoW = (PtrGetNamedSecurityInfoW)GetProcAddress(advapiHnd, "GetNamedSecurityInfoW"); - ptrLookupAccountSidW = (PtrLookupAccountSidW)GetProcAddress(advapiHnd, "LookupAccountSidW"); - ptrAllocateAndInitializeSid = (PtrAllocateAndInitializeSid)GetProcAddress(advapiHnd, "AllocateAndInitializeSid"); - ptrBuildTrusteeWithSidW = (PtrBuildTrusteeWithSidW)GetProcAddress(advapiHnd, "BuildTrusteeWithSidW"); - ptrBuildTrusteeWithNameW = (PtrBuildTrusteeWithNameW)GetProcAddress(advapiHnd, "BuildTrusteeWithNameW"); - ptrGetEffectiveRightsFromAclW = (PtrGetEffectiveRightsFromAclW)GetProcAddress(advapiHnd, "GetEffectiveRightsFromAclW"); - ptrFreeSid = (PtrFreeSid)GetProcAddress(advapiHnd, "FreeSid"); - } - if (ptrBuildTrusteeWithNameW) { - HINSTANCE versionHnd = LoadLibraryW(L"version"); - if (versionHnd) { - typedef DWORD (WINAPI *PtrGetFileVersionInfoSizeW)(LPWSTR lptstrFilename,LPDWORD lpdwHandle); - PtrGetFileVersionInfoSizeW ptrGetFileVersionInfoSizeW = (PtrGetFileVersionInfoSizeW)GetProcAddress(versionHnd, "GetFileVersionInfoSizeW"); - typedef BOOL (WINAPI *PtrGetFileVersionInfoW)(LPWSTR lptstrFilename,DWORD dwHandle,DWORD dwLen,LPVOID lpData); - PtrGetFileVersionInfoW ptrGetFileVersionInfoW = (PtrGetFileVersionInfoW)GetProcAddress(versionHnd, "GetFileVersionInfoW"); - typedef BOOL (WINAPI *PtrVerQueryValueW)(const LPVOID pBlock,LPWSTR lpSubBlock,LPVOID *lplpBuffer,PUINT puLen); - PtrVerQueryValueW ptrVerQueryValueW = (PtrVerQueryValueW)GetProcAddress(versionHnd, "VerQueryValueW"); - if(ptrGetFileVersionInfoSizeW && ptrGetFileVersionInfoW && ptrVerQueryValueW) { - DWORD fakeHandle; - DWORD versionSize = ptrGetFileVersionInfoSizeW(L"secur32.dll", &fakeHandle); - if(versionSize) { - LPVOID versionData; - versionData = malloc(versionSize); - if(ptrGetFileVersionInfoW(L"secur32.dll", 0, versionSize, versionData)) { - UINT puLen; - VS_FIXEDFILEINFO *pLocalInfo; - if(ptrVerQueryValueW(versionData, L"\\", (void**)&pLocalInfo, &puLen)) { - WORD wVer1, wVer2, wVer3, wVer4; - wVer1 = HIWORD(pLocalInfo->dwFileVersionMS); - wVer2 = LOWORD(pLocalInfo->dwFileVersionMS); - wVer3 = HIWORD(pLocalInfo->dwFileVersionLS); - wVer4 = LOWORD(pLocalInfo->dwFileVersionLS); - // It will not work with secur32.dll version 5.0.2195.2862 - if(!(wVer1 == 5 && wVer2 == 0 && wVer3 == 2195 && (wVer4 == 2862 || wVer4 == 4587))) { - HINSTANCE userHnd = LoadLibraryW(L"secur32"); - if (userHnd) { - typedef BOOL (WINAPI *PtrGetUserNameExW)(EXTENDED_NAME_FORMAT nameFormat, ushort* lpBuffer, LPDWORD nSize); - PtrGetUserNameExW ptrGetUserNameExW = (PtrGetUserNameExW)GetProcAddress(userHnd, "GetUserNameExW"); - if(ptrGetUserNameExW) { - static TCHAR buffer[258]; - DWORD bufferSize = 257; - ptrGetUserNameExW(NameSamCompatible, (ushort*)buffer, &bufferSize); - ptrBuildTrusteeWithNameW(¤tUserTrusteeW, (ushort*)buffer); - } - FreeLibrary(userHnd); + HINSTANCE advapiHnd = LoadLibraryW(L"advapi32"); + if (advapiHnd) { + ptrGetNamedSecurityInfoW = (PtrGetNamedSecurityInfoW)GetProcAddress(advapiHnd, "GetNamedSecurityInfoW"); + ptrLookupAccountSidW = (PtrLookupAccountSidW)GetProcAddress(advapiHnd, "LookupAccountSidW"); + ptrAllocateAndInitializeSid = (PtrAllocateAndInitializeSid)GetProcAddress(advapiHnd, "AllocateAndInitializeSid"); + ptrBuildTrusteeWithSidW = (PtrBuildTrusteeWithSidW)GetProcAddress(advapiHnd, "BuildTrusteeWithSidW"); + ptrBuildTrusteeWithNameW = (PtrBuildTrusteeWithNameW)GetProcAddress(advapiHnd, "BuildTrusteeWithNameW"); + ptrGetEffectiveRightsFromAclW = (PtrGetEffectiveRightsFromAclW)GetProcAddress(advapiHnd, "GetEffectiveRightsFromAclW"); + ptrFreeSid = (PtrFreeSid)GetProcAddress(advapiHnd, "FreeSid"); + } + if (ptrBuildTrusteeWithNameW) { + HINSTANCE versionHnd = LoadLibraryW(L"version"); + if (versionHnd) { + typedef DWORD (WINAPI *PtrGetFileVersionInfoSizeW)(LPWSTR lptstrFilename,LPDWORD lpdwHandle); + PtrGetFileVersionInfoSizeW ptrGetFileVersionInfoSizeW = (PtrGetFileVersionInfoSizeW)GetProcAddress(versionHnd, "GetFileVersionInfoSizeW"); + typedef BOOL (WINAPI *PtrGetFileVersionInfoW)(LPWSTR lptstrFilename,DWORD dwHandle,DWORD dwLen,LPVOID lpData); + PtrGetFileVersionInfoW ptrGetFileVersionInfoW = (PtrGetFileVersionInfoW)GetProcAddress(versionHnd, "GetFileVersionInfoW"); + typedef BOOL (WINAPI *PtrVerQueryValueW)(const LPVOID pBlock,LPWSTR lpSubBlock,LPVOID *lplpBuffer,PUINT puLen); + PtrVerQueryValueW ptrVerQueryValueW = (PtrVerQueryValueW)GetProcAddress(versionHnd, "VerQueryValueW"); + if(ptrGetFileVersionInfoSizeW && ptrGetFileVersionInfoW && ptrVerQueryValueW) { + DWORD fakeHandle; + DWORD versionSize = ptrGetFileVersionInfoSizeW(L"secur32.dll", &fakeHandle); + if(versionSize) { + LPVOID versionData; + versionData = malloc(versionSize); + if(ptrGetFileVersionInfoW(L"secur32.dll", 0, versionSize, versionData)) { + UINT puLen; + VS_FIXEDFILEINFO *pLocalInfo; + if(ptrVerQueryValueW(versionData, L"\\", (void**)&pLocalInfo, &puLen)) { + WORD wVer1, wVer2, wVer3, wVer4; + wVer1 = HIWORD(pLocalInfo->dwFileVersionMS); + wVer2 = LOWORD(pLocalInfo->dwFileVersionMS); + wVer3 = HIWORD(pLocalInfo->dwFileVersionLS); + wVer4 = LOWORD(pLocalInfo->dwFileVersionLS); + // It will not work with secur32.dll version 5.0.2195.2862 + if(!(wVer1 == 5 && wVer2 == 0 && wVer3 == 2195 && (wVer4 == 2862 || wVer4 == 4587))) { + HINSTANCE userHnd = LoadLibraryW(L"secur32"); + if (userHnd) { + typedef BOOL (WINAPI *PtrGetUserNameExW)(EXTENDED_NAME_FORMAT nameFormat, ushort* lpBuffer, LPDWORD nSize); + PtrGetUserNameExW ptrGetUserNameExW = (PtrGetUserNameExW)GetProcAddress(userHnd, "GetUserNameExW"); + if(ptrGetUserNameExW) { + static wchar_t buffer[258]; + DWORD bufferSize = 257; + ptrGetUserNameExW(NameSamCompatible, (ushort*)buffer, &bufferSize); + ptrBuildTrusteeWithNameW(¤tUserTrusteeW, (ushort*)buffer); } + FreeLibrary(userHnd); } } } - free(versionData); } + free(versionData); } - FreeLibrary(versionHnd); } + FreeLibrary(versionHnd); } ptrOpenProcessToken = (PtrOpenProcessToken)GetProcAddress(advapiHnd, "OpenProcessToken"); - HINSTANCE userenvHnd = LoadLibraryW(L"userenv"); + HINSTANCE userenvHnd = LoadLibraryW(L"userenv"); if (userenvHnd) { ptrGetUserProfileDirectoryW = (PtrGetUserProfileDirectoryW)GetProcAddress(userenvHnd, "GetUserProfileDirectoryW"); } @@ -225,120 +223,60 @@ void QFSFileEnginePrivate::resolveLibs() #endif // QT_NO_LIBRARY // UNC functions NT -typedef DWORD (WINAPI *PtrNetShareEnum_NT)(LPWSTR, DWORD, LPBYTE*, DWORD, LPDWORD, LPDWORD, LPDWORD); -static PtrNetShareEnum_NT ptrNetShareEnum_NT = 0; -typedef DWORD (WINAPI *PtrNetApiBufferFree_NT)(LPVOID); -static PtrNetApiBufferFree_NT ptrNetApiBufferFree_NT = 0; -typedef struct _SHARE_INFO_1_NT { +typedef DWORD (WINAPI *PtrNetShareEnum)(LPWSTR, DWORD, LPBYTE*, DWORD, LPDWORD, LPDWORD, LPDWORD); +static PtrNetShareEnum ptrNetShareEnum = 0; +typedef DWORD (WINAPI *PtrNetApiBufferFree)(LPVOID); +static PtrNetApiBufferFree ptrNetApiBufferFree = 0; +typedef struct _SHARE_INFO_1 { LPWSTR shi1_netname; DWORD shi1_type; LPWSTR shi1_remark; -} SHARE_INFO_1_NT; +} SHARE_INFO_1; -bool QFSFileEnginePrivate::resolveUNCLibs_NT() +bool QFSFileEnginePrivate::resolveUNCLibs() { static bool triedResolve = false; if (!triedResolve) { #ifndef QT_NO_THREAD QMutexLocker locker(QMutexPool::globalInstanceGet(&triedResolve)); if (triedResolve) { - return ptrNetShareEnum_NT && ptrNetApiBufferFree_NT; + return ptrNetShareEnum && ptrNetApiBufferFree; } #endif triedResolve = true; #if !defined(Q_OS_WINCE) HINSTANCE hLib = LoadLibraryW(L"Netapi32"); if (hLib) { - ptrNetShareEnum_NT = (PtrNetShareEnum_NT)GetProcAddress(hLib, "NetShareEnum"); - if (ptrNetShareEnum_NT) - ptrNetApiBufferFree_NT = (PtrNetApiBufferFree_NT)GetProcAddress(hLib, "NetApiBufferFree"); - } -#endif - } - return ptrNetShareEnum_NT && ptrNetApiBufferFree_NT; -} - -// UNC functions 9x -typedef DWORD (WINAPI *PtrNetShareEnum_9x)(const char FAR *, short, char FAR *, unsigned short, unsigned short FAR *, unsigned short FAR *); -static PtrNetShareEnum_9x ptrNetShareEnum_9x = 0; -#ifdef LM20_NNLEN -# define LM20_NNLEN_9x LM20_NNLEN -#else -# define LM20_NNLEN_9x 12 -#endif -typedef struct _SHARE_INFO_1_9x { - char shi1_netname[LM20_NNLEN_9x+1]; - char shi1_pad1; - unsigned short shi1_type; - char FAR* shi1_remark; -} SHARE_INFO_1_9x; - -bool QFSFileEnginePrivate::resolveUNCLibs_9x() -{ - static bool triedResolve = false; - if (!triedResolve) { -#ifndef QT_NO_THREAD - QMutexLocker locker(QMutexPool::globalInstanceGet(&triedResolve)); - if (triedResolve) { - return ptrNetShareEnum_9x; + ptrNetShareEnum = (PtrNetShareEnum)GetProcAddress(hLib, "NetShareEnum"); + if (ptrNetShareEnum) + ptrNetApiBufferFree = (PtrNetApiBufferFree)GetProcAddress(hLib, "NetApiBufferFree"); } #endif - triedResolve = true; -#if !defined(Q_OS_WINCE) - HINSTANCE hLib = LoadLibraryA("Svrapi"); - if (hLib) - ptrNetShareEnum_9x = (PtrNetShareEnum_9x)GetProcAddress(hLib, "NetShareEnum"); -#endif } - return ptrNetShareEnum_9x; + return ptrNetShareEnum && ptrNetApiBufferFree; } bool QFSFileEnginePrivate::uncListSharesOnServer(const QString &server, QStringList *list) { - if (resolveUNCLibs_NT()) { - SHARE_INFO_1_NT *BufPtr, *p; + if (resolveUNCLibs()) { + SHARE_INFO_1 *BufPtr, *p; DWORD res; DWORD er=0,tr=0,resume=0, i; do { - res = ptrNetShareEnum_NT((wchar_t*)server.utf16(), 1, (LPBYTE *)&BufPtr, DWORD(-1), &er, &tr, &resume); + res = ptrNetShareEnum((wchar_t*)server.utf16(), 1, (LPBYTE *)&BufPtr, DWORD(-1), &er, &tr, &resume); if (res == ERROR_SUCCESS || res == ERROR_MORE_DATA) { p=BufPtr; for (i = 1; i <= er; ++i) { if (list && p->shi1_type == 0) - list->append(QString::fromUtf16((unsigned short *)p->shi1_netname)); + list->append(QString::fromWCharArray(p->shi1_netname)); p++; } } - ptrNetApiBufferFree_NT(BufPtr); + ptrNetApiBufferFree(BufPtr); } while (res==ERROR_MORE_DATA); return res == ERROR_SUCCESS; - } else if (resolveUNCLibs_9x()) { - SHARE_INFO_1_9x *pBuf = 0; - short cbBuffer; - unsigned short nEntriesRead = 0; - unsigned short nTotalEntries = 0; - short numBuffs = 20; - DWORD nStatus = 0; - do { - cbBuffer = numBuffs * sizeof(SHARE_INFO_1_9x); - pBuf = (SHARE_INFO_1_9x *)malloc(cbBuffer); - if (pBuf) { - nStatus = ptrNetShareEnum_9x(server.toLocal8Bit().constData(), 1, (char FAR *)pBuf, cbBuffer, &nEntriesRead, &nTotalEntries); - if ((nStatus == ERROR_SUCCESS)) { - for (int i = 0; i < nEntriesRead; ++i) { - if (list && pBuf[i].shi1_type == 0) - list->append(QString::fromLocal8Bit(pBuf[i].shi1_netname)); - } - free(pBuf); - break; - } - free(pBuf); - numBuffs *=2; - } - } while (nStatus == ERROR_MORE_DATA); - return nStatus == ERROR_SUCCESS; } return false; } @@ -399,39 +337,19 @@ static bool uncShareExists(const QString &server) return false; } -#if !defined(Q_OS_WINCE) -// If you change this function, remember to also change the UNICODE version -static QString nativeAbsoluteFilePathA(const QString &path) -{ - QString ret; - QVarLengthArray buf(MAX_PATH); - char *fileName = 0; - QByteArray ba = path.toLocal8Bit(); - DWORD retLen = GetFullPathNameA(ba.constData(), buf.size(), buf.data(), &fileName); - if (retLen > (DWORD)buf.size()) { - buf.resize(retLen); - retLen = GetFullPathNameA(ba.constData(), buf.size(), buf.data(), &fileName); - } - if (retLen != 0) - ret = QString::fromLocal8Bit(buf.data(), retLen); - return ret; -} -#endif - -// If you change this function, remember to also change the NON-UNICODE version -static QString nativeAbsoluteFilePathW(const QString &path) +static QString nativeAbsoluteFilePathCore(const QString &path) { QString ret; #if !defined(Q_OS_WINCE) QVarLengthArray buf(MAX_PATH); wchar_t *fileName = 0; - DWORD retLen = GetFullPathNameW((wchar_t*)path.utf16(), buf.size(), buf.data(), &fileName); + DWORD retLen = GetFullPathName((wchar_t*)path.utf16(), buf.size(), buf.data(), &fileName); if (retLen > (DWORD)buf.size()) { buf.resize(retLen); - retLen = GetFullPathNameW((wchar_t*)path.utf16(), buf.size(), buf.data(), &fileName); + retLen = GetFullPathName((wchar_t*)path.utf16(), buf.size(), buf.data(), &fileName); } if (retLen != 0) - ret = QString::fromUtf16((unsigned short *)buf.data(), retLen); + ret = QString::fromWCharArray(buf.data(), retLen); #else if (path.startsWith(QLatin1Char('/')) || path.startsWith(QLatin1Char('\\'))) ret = QDir::toNativeSeparators(path); @@ -443,7 +361,7 @@ static QString nativeAbsoluteFilePathW(const QString &path) static QString nativeAbsoluteFilePath(const QString &path) { - QString absPath = QT_WA_INLINE(nativeAbsoluteFilePathW(path), nativeAbsoluteFilePathA(path)); + QString absPath = nativeAbsoluteFilePathCore(path); // This is really ugly, but GetFullPathName strips off whitespace at the end. // If you for instance write ". " in the lineedit of QFileDialog, // (which is an invalid filename) this function will strip the space off and viola, @@ -461,26 +379,6 @@ static QString nativeAbsoluteFilePath(const QString &path) return absPath; } -QByteArray QFSFileEnginePrivate::win95Name(const QString &path) -{ - QString ret(path); - if(path.length() > 1 && path[0] == QLatin1Char('/') && path[1] == QLatin1Char('/')) { - // Win95 cannot handle slash-slash needs slosh-slosh. - ret[0] = QLatin1Char('\\'); - ret[1] = QLatin1Char('\\'); - int n = ret.indexOf(QLatin1Char('/')); - if(n >= 0) - ret[n] = QLatin1Char('\\'); - } else if(path.length() > 3 && path[2] == QLatin1Char('/') && path[3] == QLatin1Char('/')) { - ret[2] = QLatin1Char('\\'); - ret.remove(3, 1); - int n = ret.indexOf(QLatin1Char('/')); - if(n >= 0) - ret[n] = QLatin1Char('\\'); - } - return ret.toLocal8Bit(); -} - /*! \internal */ @@ -507,13 +405,8 @@ QString QFSFileEnginePrivate::longFileName(const QString &path) */ void QFSFileEnginePrivate::nativeInitFileName() { - QT_WA({ - QString path = longFileName(QDir::toNativeSeparators(fixIfRelativeUncPath(filePath))); - nativeFilePath = QByteArray((const char *)path.utf16(), path.size() * 2 + 1); - }, { - QString path = fixIfRelativeUncPath(filePath); - nativeFilePath = win95Name(path).replace('/', '\\'); - }); + QString path = longFileName(QDir::toNativeSeparators(fixIfRelativeUncPath(filePath))); + nativeFilePath = QByteArray((const char *)path.utf16(), path.size() * 2 + 1); } /* @@ -539,23 +432,13 @@ bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode) ? OPEN_ALWAYS : OPEN_EXISTING; // Create the file handle. - QT_WA({ - fileHandle = CreateFileW((TCHAR *)nativeFilePath.constData(), - accessRights, - shareMode, - &securityAtts, - creationDisp, - FILE_ATTRIBUTE_NORMAL, - NULL); - }, { - fileHandle = CreateFileA(nativeFilePath.constData(), - accessRights, - shareMode, - &securityAtts, - creationDisp, - FILE_ATTRIBUTE_NORMAL, - NULL); - }); + fileHandle = CreateFile((const wchar_t*)nativeFilePath.constData(), + accessRights, + shareMode, + &securityAtts, + creationDisp, + FILE_ATTRIBUTE_NORMAL, + NULL); // Bail out on error. if (fileHandle == INVALID_HANDLE_VALUE) { @@ -641,15 +524,9 @@ qint64 QFSFileEnginePrivate::nativeSize() const // Not-open mode, where the file name is known: We'll check the // file system directly. if (openMode == QIODevice::NotOpen && !nativeFilePath.isEmpty()) { - bool ok = false; WIN32_FILE_ATTRIBUTE_DATA attribData; - QT_WA({ - ok = ::GetFileAttributesExW((TCHAR *)nativeFilePath.constData(), - GetFileExInfoStandard, &attribData); - } , { - ok = ::GetFileAttributesExA(nativeFilePath.constData(), + bool ok = ::GetFileAttributesEx((const wchar_t*)nativeFilePath.constData(), GetFileExInfoStandard, &attribData); - }); if (ok) { qint64 size = attribData.nFileSizeHigh; size <<= 32; @@ -949,35 +826,21 @@ bool QFSFileEnginePrivate::nativeIsSequential() const bool QFSFileEngine::remove() { Q_D(QFSFileEngine); - QT_WA({ - return ::DeleteFileW((TCHAR*)QFSFileEnginePrivate::longFileName(d->filePath).utf16()) != 0; - } , { - return ::DeleteFileA(QFSFileEnginePrivate::win95Name(d->filePath)) != 0; - }); + return ::DeleteFile((wchar_t*)QFSFileEnginePrivate::longFileName(d->filePath).utf16()) != 0; } bool QFSFileEngine::copy(const QString ©Name) { Q_D(QFSFileEngine); - QT_WA({ - return ::CopyFileW((TCHAR*)QFSFileEnginePrivate::longFileName(d->filePath).utf16(), - (TCHAR*)QFSFileEnginePrivate::longFileName(copyName).utf16(), true) != 0; - } , { - return ::CopyFileA(QFSFileEnginePrivate::win95Name(d->filePath), - QFSFileEnginePrivate::win95Name(copyName), true) != 0; - }); + return ::CopyFile((wchar_t*)QFSFileEnginePrivate::longFileName(d->filePath).utf16(), + (wchar_t*)QFSFileEnginePrivate::longFileName(copyName).utf16(), true) != 0; } bool QFSFileEngine::rename(const QString &newName) { Q_D(QFSFileEngine); - QT_WA({ - return ::MoveFileW((TCHAR*)QFSFileEnginePrivate::longFileName(d->filePath).utf16(), - (TCHAR*)QFSFileEnginePrivate::longFileName(newName).utf16()) != 0; - } , { - return ::MoveFileA(QFSFileEnginePrivate::win95Name(d->filePath), - QFSFileEnginePrivate::win95Name(newName)) != 0; - }); + return ::MoveFile((wchar_t*)QFSFileEnginePrivate::longFileName(d->filePath).utf16(), + (wchar_t*)QFSFileEnginePrivate::longFileName(newName).utf16()) != 0; } static inline bool mkDir(const QString &path) @@ -1001,20 +864,12 @@ static inline bool mkDir(const QString &path) if (platformId == 1 && QFSFileEnginePrivate::longFileName(path).size() > 256) return false; #endif - QT_WA({ - return ::CreateDirectoryW((TCHAR*)QFSFileEnginePrivate::longFileName(path).utf16(), 0); - } , { - return ::CreateDirectoryA(QFSFileEnginePrivate::win95Name(QFileInfo(path).absoluteFilePath()), 0); - }); + return ::CreateDirectory((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16(), 0); } static inline bool rmDir(const QString &path) { - QT_WA({ - return ::RemoveDirectoryW((TCHAR*)QFSFileEnginePrivate::longFileName(path).utf16()); - } , { - return ::RemoveDirectoryA(QFSFileEnginePrivate::win95Name(QFileInfo(path).absoluteFilePath())); - }); + return ::RemoveDirectory((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16()); } static inline bool isDirPath(const QString &dirPath, bool *existed) @@ -1023,12 +878,7 @@ static inline bool isDirPath(const QString &dirPath, bool *existed) if (path.length() == 2 &&path.at(1) == QLatin1Char(':')) path += QLatin1Char('\\'); - DWORD fileAttrib = INVALID_FILE_ATTRIBUTES; - QT_WA({ - fileAttrib = ::GetFileAttributesW((TCHAR*)QFSFileEnginePrivate::longFileName(path).utf16()); - } , { - fileAttrib = ::GetFileAttributesA(QFSFileEnginePrivate::win95Name(QFileInfo(path).absoluteFilePath())); - }); + DWORD fileAttrib = ::GetFileAttributes((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16()); if (existed) *existed = fileAttrib != INVALID_FILE_ATTRIBUTES; @@ -1110,16 +960,10 @@ bool QFSFileEngine::setCurrentPath(const QString &path) return false; #if !defined(Q_OS_WINCE) - int r; - QT_WA({ - r = ::SetCurrentDirectoryW((WCHAR*)path.utf16()); - } , { - r = ::SetCurrentDirectoryA(QFSFileEnginePrivate::win95Name(path)); - }); - return r != 0; + return ::SetCurrentDirectory((wchar_t*)path.utf16()) != 0; #else - qfsPrivateCurrentDir = QFSFileEnginePrivate::longFileName(path); - return true; + qfsPrivateCurrentDir = QFSFileEnginePrivate::longFileName(path); + return true; #endif } @@ -1132,48 +976,34 @@ QString QFSFileEngine::currentPath(const QString &fileName) fileName.at(0).isLetter() && fileName.at(1) == QLatin1Char(':')) { int drv = fileName.toUpper().at(0).toLatin1() - 'A' + 1; if (_getdrive() != drv) { - QT_WA({ - TCHAR buf[PATH_MAX]; - ::_wgetdcwd(drv, buf, PATH_MAX); - ret.setUtf16((ushort*)buf, uint(::wcslen(buf))); - }, { - char buf[PATH_MAX]; - ::_getdcwd(drv, buf, PATH_MAX); - ret = QString::fromLatin1(buf); - }); + wchar_t buf[PATH_MAX]; + ::_wgetdcwd(drv, buf, PATH_MAX); + ret = QString::fromWCharArray(buf); } } if (ret.isEmpty()) { //just the pwd - QT_WA({ - DWORD size = 0; - WCHAR currentName[PATH_MAX]; - size = ::GetCurrentDirectoryW(PATH_MAX, currentName); - if (size !=0) { - if (size > PATH_MAX) { - WCHAR * newCurrentName = new WCHAR[size]; - if (::GetCurrentDirectoryW(PATH_MAX, newCurrentName) != 0) - ret = QString::fromUtf16((ushort*)newCurrentName); - delete [] newCurrentName; - } else { - ret = QString::fromUtf16((ushort*)currentName); - } + DWORD size = 0; + wchar_t currentName[PATH_MAX]; + size = ::GetCurrentDirectory(PATH_MAX, currentName); + if (size != 0) { + if (size > PATH_MAX) { + wchar_t *newCurrentName = new wchar_t[size]; + if (::GetCurrentDirectory(PATH_MAX, newCurrentName) != 0) + ret = QString::fromWCharArray(newCurrentName); + delete [] newCurrentName; + } else { + ret = QString::fromWCharArray(currentName); } - } , { - DWORD size = 0; - char currentName[PATH_MAX]; - size = ::GetCurrentDirectoryA(PATH_MAX, currentName); - if (size !=0) - ret = QString::fromLocal8Bit(currentName); - }); + } } if (ret.length() >= 2 && ret[1] == QLatin1Char(':')) ret[0] = ret.at(0).toUpper(); // Force uppercase drive letters. return QDir::fromNativeSeparators(ret); #else - Q_UNUSED(fileName); - if (qfsPrivateCurrentDir.isEmpty()) - qfsPrivateCurrentDir = QCoreApplication::applicationDirPath(); + Q_UNUSED(fileName); + if (qfsPrivateCurrentDir.isEmpty()) + qfsPrivateCurrentDir = QCoreApplication::applicationDirPath(); return QDir::fromNativeSeparators(qfsPrivateCurrentDir); #endif @@ -1183,35 +1013,27 @@ QString QFSFileEngine::homePath() { QString ret; #if !defined(QT_NO_LIBRARY) - QT_WA ( - { - QFSFileEnginePrivate::resolveLibs(); - if (ptrOpenProcessToken && ptrGetUserProfileDirectoryW) { - HANDLE hnd = ::GetCurrentProcess(); - HANDLE token = 0; - BOOL ok = ::ptrOpenProcessToken(hnd, TOKEN_QUERY, &token); - if (ok) { - DWORD dwBufferSize = 0; - // First call, to determine size of the strings (with '\0'). - ok = ::ptrGetUserProfileDirectoryW(token, NULL, &dwBufferSize); - if (!ok && dwBufferSize != 0) { // We got the required buffer size - wchar_t *userDirectory = new wchar_t[dwBufferSize]; - // Second call, now we can fill the allocated buffer. - ok = ::ptrGetUserProfileDirectoryW(token, userDirectory, &dwBufferSize); - if (ok) - ret = QString::fromUtf16((ushort*)userDirectory); - - delete [] userDirectory; - } - ::CloseHandle(token); - } - } - } - , - { - // GetUserProfileDirectory is only available from NT 4.0, - // so fall through for Win98 and friends version. - }) + QFSFileEnginePrivate::resolveLibs(); + if (ptrOpenProcessToken && ptrGetUserProfileDirectoryW) { + HANDLE hnd = ::GetCurrentProcess(); + HANDLE token = 0; + BOOL ok = ::ptrOpenProcessToken(hnd, TOKEN_QUERY, &token); + if (ok) { + DWORD dwBufferSize = 0; + // First call, to determine size of the strings (with '\0'). + ok = ::ptrGetUserProfileDirectoryW(token, NULL, &dwBufferSize); + if (!ok && dwBufferSize != 0) { // We got the required buffer size + wchar_t *userDirectory = new wchar_t[dwBufferSize]; + // Second call, now we can fill the allocated buffer. + ok = ::ptrGetUserProfileDirectoryW(token, userDirectory, &dwBufferSize); + if (ok) + ret = QString::fromWCharArray(userDirectory); + + delete [] userDirectory; + } + ::CloseHandle(token); + } + } #endif if(ret.isEmpty() || !QFile::exists(ret)) { ret = QString::fromLocal8Bit(qgetenv("USERPROFILE").constData()); @@ -1251,17 +1073,10 @@ QString QFSFileEngine::rootPath() QString QFSFileEngine::tempPath() { - QString ret; - int success; - QT_WA({ - wchar_t tempPath[MAX_PATH]; - success = GetTempPathW(MAX_PATH, tempPath); - ret = QString::fromUtf16((ushort*)tempPath); - } , { - char tempPath[MAX_PATH]; - success = GetTempPathA(MAX_PATH, tempPath); - ret = QString::fromLocal8Bit(tempPath); - }); + wchar_t tempPath[MAX_PATH]; + int success = GetTempPath(MAX_PATH, tempPath); + QString ret = QString::fromWCharArray(tempPath); + if (ret.isEmpty() || !success) { #if !defined(Q_OS_WINCE) ret = QString::fromLatin1("c:/tmp"); @@ -1285,7 +1100,7 @@ QFileInfoList QFSFileEngine::drives() #elif defined(Q_OS_OS2EMX) quint32 driveBits, cur; if(DosQueryCurrentDisk(&cur,&driveBits) != NO_ERROR) - exit(1); + exit(1); driveBits &= 0x3ffffff; #endif char driveName[] = "A:/"; @@ -1327,18 +1142,14 @@ bool QFSFileEnginePrivate::doStat() const } } #else - DWORD tmpAttributes = GetFileAttributesW((TCHAR*)QFSFileEnginePrivate::longFileName(fname).utf16()); + DWORD tmpAttributes = GetFileAttributes((wchar_t*)QFSFileEnginePrivate::longFileName(fname).utf16()); if (tmpAttributes != -1) { fileAttrib = tmpAttributes; could_stat = true; } #endif } else { - QT_WA({ - fileAttrib = GetFileAttributesW((TCHAR*)QFSFileEnginePrivate::longFileName(fname).utf16()); - } , { - fileAttrib = GetFileAttributesA(QFSFileEnginePrivate::win95Name(QFileInfo(fname).absoluteFilePath())); - }); + fileAttrib = GetFileAttributes((wchar_t*)QFSFileEnginePrivate::longFileName(fname).utf16()); could_stat = fileAttrib != INVALID_FILE_ATTRIBUTES; if (!could_stat) { #if !defined(Q_OS_WINCE) @@ -1398,74 +1209,39 @@ static QString readLink(const QString &link) #if !defined(Q_OS_WINCE) #if !defined(QT_NO_LIBRARY) QString ret; - QT_WA({ - bool neededCoInit = false; - IShellLink *psl; // pointer to IShellLink i/f - HRESULT hres; - WIN32_FIND_DATA wfd; - TCHAR szGotPath[MAX_PATH]; - // Get pointer to the IShellLink interface. - hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, - IID_IShellLink, (LPVOID *)&psl); - if(hres == CO_E_NOTINITIALIZED) { // COM was not initialized - neededCoInit = true; - CoInitialize(NULL); - hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, - IID_IShellLink, (LPVOID *)&psl); - } - if(SUCCEEDED(hres)) { // Get pointer to the IPersistFile interface. - IPersistFile *ppf; - hres = psl->QueryInterface(IID_IPersistFile, (LPVOID *)&ppf); - if(SUCCEEDED(hres)) { - hres = ppf->Load((LPOLESTR)link.utf16(), STGM_READ); - //The original path of the link is retrieved. If the file/folder - //was moved, the return value still have the old path. - if(SUCCEEDED(hres)) { - if (psl->GetPath(szGotPath, MAX_PATH, &wfd, SLGP_UNCPRIORITY) == NOERROR) - ret = QString::fromUtf16((ushort*)szGotPath); - } - ppf->Release(); - } - psl->Release(); - } - if(neededCoInit) - CoUninitialize(); - } , { - bool neededCoInit = false; - IShellLinkA *psl; // pointer to IShellLink i/f - HRESULT hres; - WIN32_FIND_DATAA wfd; - char szGotPath[MAX_PATH]; - // Get pointer to the IShellLink interface. + bool neededCoInit = false; + IShellLink *psl; // pointer to IShellLink i/f + WIN32_FIND_DATA wfd; + wchar_t szGotPath[MAX_PATH]; - hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, - IID_IShellLinkA, (LPVOID *)&psl); + // Get pointer to the IShellLink interface. + HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID *)&psl); - if(hres == CO_E_NOTINITIALIZED) { // COM was not initialized - neededCoInit = true; - CoInitialize(NULL); - hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, - IID_IShellLinkA, (LPVOID *)&psl); - } - if(SUCCEEDED(hres)) { // Get pointer to the IPersistFile interface. - IPersistFile *ppf; - hres = psl->QueryInterface(IID_IPersistFile, (LPVOID *)&ppf); - if(SUCCEEDED(hres)) { - hres = ppf->Load((LPOLESTR)QFileInfo(link).absoluteFilePath().utf16(), STGM_READ); - //The original path of the link is retrieved. If the file/folder - //was moved, the return value still have the old path. - if(SUCCEEDED(hres)) { - if (psl->GetPath((char*)szGotPath, MAX_PATH, &wfd, SLGP_UNCPRIORITY) == NOERROR) - ret = QString::fromLocal8Bit(szGotPath); - } - ppf->Release(); + if (hres == CO_E_NOTINITIALIZED) { // COM was not initialized + neededCoInit = true; + CoInitialize(NULL); + hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, + IID_IShellLink, (LPVOID *)&psl); + } + if (SUCCEEDED(hres)) { // Get pointer to the IPersistFile interface. + IPersistFile *ppf; + hres = psl->QueryInterface(IID_IPersistFile, (LPVOID *)&ppf); + if(SUCCEEDED(hres)) { + hres = ppf->Load((LPOLESTR)link.utf16(), STGM_READ); + //The original path of the link is retrieved. If the file/folder + //was moved, the return value still have the old path. + if(SUCCEEDED(hres)) { + if (psl->GetPath(szGotPath, MAX_PATH, &wfd, SLGP_UNCPRIORITY) == NOERROR) + ret = QString::fromWCharArray(szGotPath); } - psl->Release(); + ppf->Release(); } - if(neededCoInit) - CoUninitialize(); - }); + psl->Release(); + } + if (neededCoInit) + CoUninitialize(); + return ret; #else Q_UNUSED(link); @@ -1475,7 +1251,7 @@ static QString readLink(const QString &link) wchar_t target[MAX_PATH]; QString result; if (SHGetShortcutTarget((wchar_t*)QFileInfo(link).absoluteFilePath().replace(QLatin1Char('/'),QLatin1Char('\\')).utf16(), target, MAX_PATH)) { - result = QString::fromUtf16(reinterpret_cast (target)); + result = QString::fromWCharArray(target); if (result.startsWith(QLatin1Char('"'))) result.remove(0,1); if (result.endsWith(QLatin1Char('"'))) @@ -1502,76 +1278,37 @@ bool QFSFileEngine::link(const QString &newName) QString linkName = newName; //### assume that they add .lnk - QT_WA({ - HRESULT hres; - IShellLink *psl; - bool neededCoInit = false; + IShellLink *psl; + bool neededCoInit = false; - hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl); - if(hres == CO_E_NOTINITIALIZED) { // COM was not initialized - neededCoInit = true; - CoInitialize(NULL); - hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl); - } - if (SUCCEEDED(hres)) { - hres = psl->SetPath((wchar_t *)fileName(AbsoluteName).replace(QLatin1Char('/'), QLatin1Char('\\')).utf16()); - if (SUCCEEDED(hres)) { - hres = psl->SetWorkingDirectory((wchar_t *)fileName(AbsolutePathName).replace(QLatin1Char('/'), QLatin1Char('\\')).utf16()); - if (SUCCEEDED(hres)) { - IPersistFile *ppf; - hres = psl->QueryInterface(IID_IPersistFile, (void **)&ppf); - if (SUCCEEDED(hres)) { - hres = ppf->Save((TCHAR*)linkName.utf16(), TRUE); - if (SUCCEEDED(hres)) - ret = true; - ppf->Release(); - } - } - } - psl->Release(); - } - if(neededCoInit) - CoUninitialize(); - } , { - // the SetPath() call _sometimes_ changes the current path and when it does it sometimes - // does not let us change it back unless we call currentPath() many times. - QString cwd = currentPath(); - HRESULT hres; - IShellLinkA *psl; - bool neededCoInit = false; + HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl); + if (hres == CO_E_NOTINITIALIZED) { // COM was not initialized + neededCoInit = true; + CoInitialize(NULL); hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl); - if(hres == CO_E_NOTINITIALIZED) { // COM was not initialized - neededCoInit = true; - CoInitialize(NULL); - hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl); - } + } + + if (SUCCEEDED(hres)) { + hres = psl->SetPath((wchar_t *)fileName(AbsoluteName).replace(QLatin1Char('/'), QLatin1Char('\\')).utf16()); if (SUCCEEDED(hres)) { - currentPath(); - hres = psl->SetPath((char *)QString::fromLocal8Bit(QFSFileEnginePrivate::win95Name(fileName(AbsoluteName))).utf16()); - currentPath(); + hres = psl->SetWorkingDirectory((wchar_t *)fileName(AbsolutePathName).replace(QLatin1Char('/'), QLatin1Char('\\')).utf16()); if (SUCCEEDED(hres)) { - hres = psl->SetWorkingDirectory((char *)QString::fromLocal8Bit(QFSFileEnginePrivate::win95Name(fileName(AbsolutePathName))).utf16()); - currentPath(); + IPersistFile *ppf; + hres = psl->QueryInterface(IID_IPersistFile, (void **)&ppf); if (SUCCEEDED(hres)) { - IPersistFile *ppf; - hres = psl->QueryInterface(IID_IPersistFile, (void **)&ppf); - if (SUCCEEDED(hres)) { - currentPath(); - hres = ppf->Save((LPCOLESTR)linkName.utf16(), TRUE); - currentPath(); - if (SUCCEEDED(hres)) - ret = true; - ppf->Release(); - } + hres = ppf->Save((wchar_t*)linkName.utf16(), TRUE); + if (SUCCEEDED(hres)) + ret = true; + ppf->Release(); } - psl->Release(); } } - if(neededCoInit) + psl->Release(); + } + if(neededCoInit) CoUninitialize(); - setCurrentPath(cwd); - }); + return ret; #else Q_UNUSED(newName); @@ -1598,9 +1335,9 @@ QAbstractFileEngine::FileFlags QFSFileEnginePrivate::getPermissions() const #if !defined(QT_NO_LIBRARY) if((qt_ntfs_permission_lookup > 0) && ((QSysInfo::WindowsVersion&QSysInfo::WV_NT_based) > QSysInfo::WV_NT)) { - PSID pOwner = 0; - PSID pGroup = 0; - PACL pDacl; + PSID pOwner = 0; + PSID pGroup = 0; + PACL pDacl; PSECURITY_DESCRIPTOR pSD; ACCESS_MASK access_mask; @@ -1610,42 +1347,42 @@ QAbstractFileEngine::FileFlags QFSFileEnginePrivate::getPermissions() const QString fname = filePath.endsWith(QLatin1String(".lnk")) ? readLink(filePath) : filePath; DWORD res = ptrGetNamedSecurityInfoW((wchar_t*)fname.utf16(), SE_FILE_OBJECT, - OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, - &pOwner, &pGroup, &pDacl, 0, &pSD); + OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, + &pOwner, &pGroup, &pDacl, 0, &pSD); if(res == ERROR_SUCCESS) { TRUSTEE_W trustee; { //user if(ptrGetEffectiveRightsFromAclW(pDacl, ¤tUserTrusteeW, &access_mask) != ERROR_SUCCESS) access_mask = (ACCESS_MASK)-1; - if(access_mask & ReadMask) - ret |= QAbstractFileEngine::ReadUserPerm; - if(access_mask & WriteMask) - ret |= QAbstractFileEngine::WriteUserPerm; - if(access_mask & ExecMask) - ret |= QAbstractFileEngine::ExeUserPerm; + if(access_mask & ReadMask) + ret |= QAbstractFileEngine::ReadUserPerm; + if(access_mask & WriteMask) + ret |= QAbstractFileEngine::WriteUserPerm; + if(access_mask & ExecMask) + ret |= QAbstractFileEngine::ExeUserPerm; } { //owner ptrBuildTrusteeWithSidW(&trustee, pOwner); if(ptrGetEffectiveRightsFromAclW(pDacl, &trustee, &access_mask) != ERROR_SUCCESS) access_mask = (ACCESS_MASK)-1; - if(access_mask & ReadMask) - ret |= QAbstractFileEngine::ReadOwnerPerm; - if(access_mask & WriteMask) - ret |= QAbstractFileEngine::WriteOwnerPerm; - if(access_mask & ExecMask) - ret |= QAbstractFileEngine::ExeOwnerPerm; + if(access_mask & ReadMask) + ret |= QAbstractFileEngine::ReadOwnerPerm; + if(access_mask & WriteMask) + ret |= QAbstractFileEngine::WriteOwnerPerm; + if(access_mask & ExecMask) + ret |= QAbstractFileEngine::ExeOwnerPerm; } { //group ptrBuildTrusteeWithSidW(&trustee, pGroup); if(ptrGetEffectiveRightsFromAclW(pDacl, &trustee, &access_mask) != ERROR_SUCCESS) access_mask = (ACCESS_MASK)-1; - if(access_mask & ReadMask) - ret |= QAbstractFileEngine::ReadGroupPerm; - if(access_mask & WriteMask) - ret |= QAbstractFileEngine::WriteGroupPerm; - if(access_mask & ExecMask) - ret |= QAbstractFileEngine::ExeGroupPerm; + if(access_mask & ReadMask) + ret |= QAbstractFileEngine::ReadGroupPerm; + if(access_mask & WriteMask) + ret |= QAbstractFileEngine::WriteGroupPerm; + if(access_mask & ExecMask) + ret |= QAbstractFileEngine::ExeGroupPerm; } { //other (world) // Create SID for Everyone (World) @@ -1655,12 +1392,12 @@ QAbstractFileEngine::FileFlags QFSFileEnginePrivate::getPermissions() const ptrBuildTrusteeWithSidW(&trustee, pWorld); if(ptrGetEffectiveRightsFromAclW(pDacl, &trustee, &access_mask) != ERROR_SUCCESS) access_mask = (ACCESS_MASK)-1; // ### - if(access_mask & ReadMask) - ret |= QAbstractFileEngine::ReadOtherPerm; - if(access_mask & WriteMask) - ret |= QAbstractFileEngine::WriteOtherPerm; - if(access_mask & ExecMask) - ret |= QAbstractFileEngine::ExeOtherPerm; + if(access_mask & ReadMask) + ret |= QAbstractFileEngine::ReadOtherPerm; + if(access_mask & WriteMask) + ret |= QAbstractFileEngine::WriteOtherPerm; + if(access_mask & ExecMask) + ret |= QAbstractFileEngine::ExeOtherPerm; } ptrFreeSid(pWorld); } @@ -1670,13 +1407,13 @@ QAbstractFileEngine::FileFlags QFSFileEnginePrivate::getPermissions() const } else #endif { - //### what to do with permissions if we don't use ntfs or are not on a NT system - // for now just add all permissions and what about exe missions ?? - // also qt_ntfs_permission_lookup is now not set by defualt ... should it ? - ret |= QAbstractFileEngine::ReadOtherPerm | QAbstractFileEngine::ReadGroupPerm - | QAbstractFileEngine::ReadOwnerPerm | QAbstractFileEngine::ReadUserPerm - | QAbstractFileEngine::WriteUserPerm | QAbstractFileEngine::WriteOwnerPerm - | QAbstractFileEngine::WriteGroupPerm | QAbstractFileEngine::WriteOtherPerm; + //### what to do with permissions if we don't use NTFS + // for now just add all permissions and what about exe missions ?? + // also qt_ntfs_permission_lookup is now not set by defualt ... should it ? + ret |= QAbstractFileEngine::ReadOtherPerm | QAbstractFileEngine::ReadGroupPerm + | QAbstractFileEngine::ReadOwnerPerm | QAbstractFileEngine::ReadUserPerm + | QAbstractFileEngine::WriteUserPerm | QAbstractFileEngine::WriteOwnerPerm + | QAbstractFileEngine::WriteGroupPerm | QAbstractFileEngine::WriteOtherPerm; } if (doStat()) { @@ -1911,13 +1648,9 @@ bool QFSFileEngine::setPermissions(uint perms) return false; #if !defined(Q_OS_WINCE) - QT_WA({ - ret = ::_wchmod((TCHAR*)d->filePath.utf16(), mode) == 0; - } , { - ret = ::_chmod(d->filePath.toLocal8Bit(), mode) == 0; - }); + ret = ::_wchmod((wchar_t*)d->filePath.utf16(), mode) == 0; #else - ret = ::_wchmod((TCHAR*)d->longFileName(d->filePath).utf16(), mode); + ret = ::_wchmod((wchar_t*)d->longFileName(d->filePath).utf16(), mode); #endif return ret; } @@ -1960,34 +1693,33 @@ bool QFSFileEngine::setSize(qint64 size) static inline QDateTime fileTimeToQDateTime(const FILETIME *time) { QDateTime ret; - if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based || QSysInfo::WindowsVersion & QSysInfo::WV_CE_based) { - // SystemTimeToTzSpecificLocalTime is not available on Win98/ME so we have to pull it off ourselves. - SYSTEMTIME systime; - FILETIME ftime; - systime.wYear = 1970; - systime.wMonth = 1; - systime.wDay = 1; - systime.wHour = 0; - systime.wMinute = 0; - systime.wSecond = 0; - systime.wMilliseconds = 0; - systime.wDayOfWeek = 4; - SystemTimeToFileTime(&systime, &ftime); - unsigned __int64 acttime = (unsigned __int64)time->dwHighDateTime << 32 | time->dwLowDateTime; - FileTimeToSystemTime(time, &systime); - unsigned __int64 time1970 = (unsigned __int64)ftime.dwHighDateTime << 32 | ftime.dwLowDateTime; - unsigned __int64 difftime = acttime - time1970; - difftime /= 10000000; - ret.setTime_t((unsigned int)difftime); - } else { -#ifndef Q_OS_WINCE - SYSTEMTIME sTime, lTime; - FileTimeToSystemTime(time, &sTime); - SystemTimeToTzSpecificLocalTime(0, &sTime, &lTime); - ret.setDate(QDate(lTime.wYear, lTime.wMonth, lTime.wDay)); - ret.setTime(QTime(lTime.wHour, lTime.wMinute, lTime.wSecond, lTime.wMilliseconds)); + +#if defined(Q_OS_WINCE) + SYSTEMTIME systime; + FILETIME ftime; + systime.wYear = 1970; + systime.wMonth = 1; + systime.wDay = 1; + systime.wHour = 0; + systime.wMinute = 0; + systime.wSecond = 0; + systime.wMilliseconds = 0; + systime.wDayOfWeek = 4; + SystemTimeToFileTime(&systime, &ftime); + unsigned __int64 acttime = (unsigned __int64)time->dwHighDateTime << 32 | time->dwLowDateTime; + FileTimeToSystemTime(time, &systime); + unsigned __int64 time1970 = (unsigned __int64)ftime.dwHighDateTime << 32 | ftime.dwLowDateTime; + unsigned __int64 difftime = acttime - time1970; + difftime /= 10000000; + ret.setTime_t((unsigned int)difftime); +#else + SYSTEMTIME sTime, lTime; + FileTimeToSystemTime(time, &sTime); + SystemTimeToTzSpecificLocalTime(0, &sTime, &lTime); + ret.setDate(QDate(lTime.wYear, lTime.wMonth, lTime.wDay)); + ret.setTime(QTime(lTime.wHour, lTime.wMinute, lTime.wSecond, lTime.wMilliseconds)); #endif - } + return ret; } @@ -2011,13 +1743,8 @@ QDateTime QFSFileEngine::fileTime(FileTime time) const } #endif } else { - bool ok = false; WIN32_FILE_ATTRIBUTE_DATA attribData; - QT_WA({ - ok = ::GetFileAttributesExW((TCHAR*)QFSFileEnginePrivate::longFileName(d->filePath).utf16(), GetFileExInfoStandard, &attribData); - } , { - ok = ::GetFileAttributesExA(QFSFileEnginePrivate::win95Name(QFileInfo(d->filePath).absoluteFilePath()), GetFileExInfoStandard, &attribData); - }); + bool ok = ::GetFileAttributesEx((wchar_t*)QFSFileEnginePrivate::longFileName(d->filePath).utf16(), GetFileExInfoStandard, &attribData); if (ok) { if(time == CreationTime) ret = fileTimeToQDateTime(&attribData.ftCreationTime); @@ -2037,11 +1764,11 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, Q_UNUSED(flags); if (openMode == QFile::NotOpen) { q->setError(QFile::PermissionsError, qt_error_string()); - return 0; + return 0; } if (offset == 0 && size == 0) { q->setError(QFile::UnspecifiedError, qt_error_string()); - return 0; + return 0; } @@ -2054,7 +1781,7 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, #ifdef Q_USE_DEPRECATED_MAP_API nativeClose(); if (fileMapHandle == INVALID_HANDLE_VALUE) { - fileMapHandle = CreateFileForMappingW((TCHAR *)nativeFilePath.constData(), + fileMapHandle = CreateFileForMapping((const wchar_t*)nativeFilePath.constData(), GENERIC_READ | (openMode & QIODevice::WriteOnly ? GENERIC_WRITE : 0), 0, NULL, @@ -2069,21 +1796,14 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, #endif // first create the file mapping handle - HANDLE mapHandle = 0; DWORD protection = (openMode & QIODevice::WriteOnly) ? PAGE_READWRITE : PAGE_READONLY; - QT_WA({ - mapHandle = ::CreateFileMappingW(handle, 0, protection, - 0, 0, 0); - },{ - mapHandle = ::CreateFileMappingA(handle, 0, protection, - 0, 0, 0); - }); + HANDLE mapHandle = ::CreateFileMapping(handle, 0, protection, 0, 0, 0); if (mapHandle == NULL) { q->setError(QFile::PermissionsError, qt_error_string()); #ifdef Q_USE_DEPRECATED_MAP_API mapHandleClose(); #endif - return 0; + return 0; } // setup args to map @@ -2112,7 +1832,7 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, switch(GetLastError()) { case ERROR_ACCESS_DENIED: q->setError(QFile::PermissionsError, qt_error_string()); - break; + break; case ERROR_INVALID_PARAMETER: // size are out of bounds default: diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp index d028df1..eae17b4 100644 --- a/src/corelib/io/qprocess_win.cpp +++ b/src/corelib/io/qprocess_win.cpp @@ -54,7 +54,7 @@ #include #include -#include "private/qfsfileengine_p.h" // for longFileName and win95FileName +#include "private/qfsfileengine_p.h" // for longFileName #ifndef QT_NO_PROCESS @@ -122,25 +122,15 @@ bool QProcessPrivate::createChannel(Channel &channel) if (&channel == &stdinChannel) { // try to open in read-only mode channel.pipe[1] = INVALID_Q_PIPE; - QT_WA({ - channel.pipe[0] = - CreateFileW((TCHAR*)QFSFileEnginePrivate::longFileName(channel.file).utf16(), - GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE, - &secAtt, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); - }, { - channel.pipe[0] = - CreateFileA(QFSFileEnginePrivate::win95Name(channel.file), - GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE, - &secAtt, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); - }); + channel.pipe[0] = + CreateFile((const wchar_t*)QFSFileEnginePrivate::longFileName(channel.file).utf16(), + GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, + &secAtt, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (channel.pipe[0] != INVALID_Q_PIPE) return true; @@ -148,31 +138,15 @@ bool QProcessPrivate::createChannel(Channel &channel) } else { // open in write mode channel.pipe[0] = INVALID_Q_PIPE; - DWORD creation; - if (channel.append) - creation = OPEN_ALWAYS; - else - creation = CREATE_ALWAYS; - - QT_WA({ - channel.pipe[1] = - CreateFileW((TCHAR*)QFSFileEnginePrivate::longFileName(channel.file).utf16(), - GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - &secAtt, - creation, - FILE_ATTRIBUTE_NORMAL, - NULL); - }, { - channel.pipe[1] = - CreateFileA(QFSFileEnginePrivate::win95Name(channel.file), - GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - &secAtt, - creation, - FILE_ATTRIBUTE_NORMAL, - NULL); - }); + channel.pipe[1] = + CreateFile((const wchar_t *)QFSFileEnginePrivate::longFileName(channel.file).utf16(), + GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + &secAtt, + channel.append ? OPEN_ALWAYS : CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (channel.pipe[1] != INVALID_Q_PIPE) { if (channel.append) { SetFilePointer(channel.pipe[1], 0, NULL, FILE_END); @@ -327,56 +301,37 @@ static QByteArray qt_create_environment(const QHash *environme int pos = 0; QHash::ConstIterator it = copy.constBegin(), end = copy.constEnd(); -#ifdef UNICODE - if (!(QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based)) { - static const TCHAR equal = L'='; - static const TCHAR nul = L'\0'; - - for ( ; it != end; ++it) { - uint tmpSize = sizeof(TCHAR) * (it.key().length() + it.value().length() + 2); - // ignore empty strings - if (tmpSize == sizeof(TCHAR)*2) - continue; - envlist.resize(envlist.size() + tmpSize); - - tmpSize = it.key().length() * sizeof(TCHAR); - memcpy(envlist.data()+pos, it.key().utf16(), tmpSize); - pos += tmpSize; - - memcpy(envlist.data()+pos, &equal, sizeof(TCHAR)); - pos += sizeof(TCHAR); - - tmpSize = it.value().length() * sizeof(TCHAR); - memcpy(envlist.data()+pos, it.value().utf16(), tmpSize); - pos += tmpSize; - - memcpy(envlist.data()+pos, &nul, sizeof(TCHAR)); - pos += sizeof(TCHAR); - } - // add the 2 terminating 0 (actually 4, just to be on the safe side) - envlist.resize( envlist.size()+4 ); - envlist[pos++] = 0; - envlist[pos++] = 0; - envlist[pos++] = 0; - envlist[pos++] = 0; - } else -#endif // UNICODE - { - for ( ; it != end; it++) { - QByteArray tmp = it.key().toLocal8Bit(); - tmp.append('='); - tmp.append(it.value().toLocal8Bit()); - - uint tmpSize = tmp.length() + 1; - envlist.resize(envlist.size() + tmpSize); - memcpy(envlist.data()+pos, tmp.data(), tmpSize); - pos += tmpSize; - } - // add the terminating 0 (actually 2, just to be on the safe side) - envlist.resize(envlist.size()+2); - envlist[pos++] = 0; - envlist[pos++] = 0; + + static const wchar_t equal = L'='; + static const wchar_t nul = L'\0'; + + for ( ; it != end; ++it) { + uint tmpSize = sizeof(wchar_t) * (it.key().length() + it.value().length() + 2); + // ignore empty strings + if (tmpSize == sizeof(wchar_t) * 2) + continue; + envlist.resize(envlist.size() + tmpSize); + + tmpSize = it.key().length() * sizeof(wchar_t); + memcpy(envlist.data()+pos, it.key().utf16(), tmpSize); + pos += tmpSize; + + memcpy(envlist.data()+pos, &equal, sizeof(wchar_t)); + pos += sizeof(wchar_t); + + tmpSize = it.value().length() * sizeof(wchar_t); + memcpy(envlist.data()+pos, it.value().utf16(), tmpSize); + pos += tmpSize; + + memcpy(envlist.data()+pos, &nul, sizeof(wchar_t)); + pos += sizeof(wchar_t); } + // add the 2 terminating 0 (actually 4, just to be on the safe side) + envlist.resize( envlist.size()+4 ); + envlist[pos++] = 0; + envlist[pos++] = 0; + envlist[pos++] = 0; + envlist[pos++] = 0; } return envlist; } @@ -417,58 +372,33 @@ void QProcessPrivate::startProcess() qDebug(" pass environment : %s", environment.isEmpty() ? "no" : "yes"); #endif - DWORD dwCreationFlags = 0; - if (!(QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based)) - dwCreationFlags |= CREATE_NO_WINDOW; + DWORD dwCreationFlags = CREATE_NO_WINDOW; -#ifdef UNICODE - if (!(QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based)) { #if defined(Q_OS_WINCE) QString fullPathProgram = program; if (!QDir::isAbsolutePath(fullPathProgram)) fullPathProgram = QFileInfo(fullPathProgram).absoluteFilePath(); fullPathProgram.replace(QLatin1Char('/'), QLatin1Char('\\')); - success = CreateProcessW((WCHAR*)fullPathProgram.utf16(), - (WCHAR*)args.utf16(), - 0, 0, false, 0, 0, 0, 0, pid); + success = CreateProcess((wchar_t*)fullPathProgram.utf16(), + (wchar_t*)args.utf16(), + 0, 0, false, 0, 0, 0, 0, pid); #else dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT; STARTUPINFOW startupInfo = { sizeof( STARTUPINFO ), 0, 0, 0, (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, - (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, - 0, 0, 0, - STARTF_USESTDHANDLES, - 0, 0, 0, - stdinChannel.pipe[0], stdoutChannel.pipe[1], stderrChannel.pipe[1] + (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, + 0, 0, 0, + STARTF_USESTDHANDLES, + 0, 0, 0, + stdinChannel.pipe[0], stdoutChannel.pipe[1], stderrChannel.pipe[1] }; - success = CreateProcessW(0, (WCHAR*)args.utf16(), - 0, 0, TRUE, dwCreationFlags, - environment ? envlist.data() : 0, - workingDirectory.isEmpty() ? 0 - : (WCHAR*)QDir::toNativeSeparators(workingDirectory).utf16(), - &startupInfo, pid); -#endif - } else -#endif // UNICODE - { -#ifndef Q_OS_WINCE - STARTUPINFOA startupInfo = { sizeof( STARTUPINFOA ), 0, 0, 0, - (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, - (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, - 0, 0, 0, - STARTF_USESTDHANDLES, - 0, 0, 0, - stdinChannel.pipe[0], stdoutChannel.pipe[1], stderrChannel.pipe[1] - }; - - success = CreateProcessA(0, args.toLocal8Bit().data(), - 0, 0, TRUE, dwCreationFlags, environment ? envlist.data() : 0, - workingDirectory.isEmpty() ? 0 - : QDir::toNativeSeparators(workingDirectory).toLocal8Bit().data(), - &startupInfo, pid); -#endif // Q_OS_WINCE - } -#ifndef Q_OS_WINCE + success = CreateProcess(0, (wchar_t*)args.utf16(), + 0, 0, TRUE, dwCreationFlags, + environment ? envlist.data() : 0, + workingDirectory.isEmpty() ? 0 + : (wchar_t*)QDir::toNativeSeparators(workingDirectory).utf16(), + &startupInfo, pid); + if (stdinChannel.pipe[0] != INVALID_Q_PIPE) { CloseHandle(stdinChannel.pipe[0]); stdinChannel.pipe[0] = INVALID_Q_PIPE; @@ -508,7 +438,7 @@ void QProcessPrivate::startProcess() } // give the process a chance to start ... - Sleep(SLEEPMIN*2); + Sleep(SLEEPMIN * 2); _q_startupNotification(); } @@ -882,42 +812,25 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a PROCESS_INFORMATION pinfo; -#ifdef UNICODE - if (!(QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based)) { #if defined(Q_OS_WINCE) QString fullPathProgram = program; if (!QDir::isAbsolutePath(fullPathProgram)) fullPathProgram.prepend(QDir::currentPath().append(QLatin1Char('/'))); fullPathProgram.replace(QLatin1Char('/'), QLatin1Char('\\')); - success = CreateProcessW((WCHAR*)fullPathProgram.utf16(), - (WCHAR*)args.utf16(), - 0, 0, false, CREATE_NEW_CONSOLE, 0, 0, 0, &pinfo); + success = CreateProcess((wchar_t*)fullPathProgram.utf16(), + (wchar_t*)args.utf16(), + 0, 0, false, CREATE_NEW_CONSOLE, 0, 0, 0, &pinfo); #else STARTUPINFOW startupInfo = { sizeof( STARTUPINFO ), 0, 0, 0, (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - success = CreateProcessW(0, (WCHAR*)args.utf16(), - 0, 0, FALSE, CREATE_UNICODE_ENVIRONMENT | CREATE_NEW_CONSOLE, 0, - workingDir.isEmpty() ? (const WCHAR *)0 : (const WCHAR *)workingDir.utf16(), - &startupInfo, &pinfo); -#endif - } else -#endif // UNICODE - { -#ifndef Q_OS_WINCE - STARTUPINFOA startupInfo = { sizeof( STARTUPINFOA ), 0, 0, 0, - (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, - (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - success = CreateProcessA(0, args.toLocal8Bit().data(), - 0, 0, FALSE, CREATE_NEW_CONSOLE, 0, - workingDir.isEmpty() ? (LPCSTR)0 : workingDir.toLocal8Bit().constData(), + success = CreateProcess(0, (wchar_t*)args.utf16(), + 0, 0, FALSE, CREATE_UNICODE_ENVIRONMENT | CREATE_NEW_CONSOLE, 0, + workingDir.isEmpty() ? 0 : (wchar_t*)workingDir.utf16(), &startupInfo, &pinfo); #endif // Q_OS_WINCE - } if (success) { CloseHandle(pinfo.hThread); diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp index 3f8dc36f..7de5030 100644 --- a/src/corelib/io/qsettings.cpp +++ b/src/corelib/io/qsettings.cpp @@ -1037,33 +1037,16 @@ static QString windowsConfigPath(int type) // This only happens when bootstrapping qmake. #ifndef Q_OS_WINCE QLibrary library(QLatin1String("shell32")); - QT_WA( { - typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, LPTSTR, int, BOOL); - GetSpecialFolderPath SHGetSpecialFolderPath = (GetSpecialFolderPath)library.resolve("SHGetSpecialFolderPathW"); - if (SHGetSpecialFolderPath) { - TCHAR path[MAX_PATH]; - SHGetSpecialFolderPath(0, path, type, FALSE); - result = QString::fromUtf16((ushort*)path); - } - } , { - typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, char*, int, BOOL); - GetSpecialFolderPath SHGetSpecialFolderPath = (GetSpecialFolderPath)library.resolve("SHGetSpecialFolderPathA"); - if (SHGetSpecialFolderPath) { - char path[MAX_PATH]; - SHGetSpecialFolderPath(0, path, type, FALSE); - result = QString::fromLocal8Bit(path); - } - } ); #else QLibrary library(QLatin1String("coredll")); - typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, LPTSTR, int, BOOL); - GetSpecialFolderPath SHGetSpecialFolderPath = (GetSpecialFolderPath)library.resolve("SHGetSpecialFolderPath"); +#endif // Q_OS_WINCE + typedef BOOL (WINAPI*GetSpecialFolderPath)(HWND, LPWSTR, int, BOOL); + GetSpecialFolderPath SHGetSpecialFolderPath = (GetSpecialFolderPath)library.resolve("SHGetSpecialFolderPathW"); if (SHGetSpecialFolderPath) { wchar_t path[MAX_PATH]; SHGetSpecialFolderPath(0, path, type, FALSE); - result = QString::fromUtf16((ushort*)path); + result = QString::fromWCharArray(path); } -#endif // Q_OS_WINCE #endif // QT_NO_QOBJECT @@ -1459,11 +1442,7 @@ void QConfFileSettingsPrivate::syncConfFile(int confFileNo) QString writeSemName = QLatin1String("QSettingsWriteSem "); writeSemName.append(file.fileName()); - QT_WA( { - writeSemaphore = CreateSemaphoreW(0, 1, 1, reinterpret_cast(writeSemName.utf16())); - } , { - writeSemaphore = CreateSemaphoreA(0, 1, 1, writeSemName.toLocal8Bit()); - } ); + writeSemaphore = CreateSemaphore(0, 1, 1, reinterpret_cast(writeSemName.utf16())); if (writeSemaphore) { WaitForSingleObject(writeSemaphore, INFINITE); @@ -1479,11 +1458,7 @@ void QConfFileSettingsPrivate::syncConfFile(int confFileNo) QString readSemName(QLatin1String("QSettingsReadSem ")); readSemName.append(file.fileName()); - QT_WA( { - readSemaphore = CreateSemaphoreW(0, FileLockSemMax, FileLockSemMax, reinterpret_cast(readSemName.utf16())); - } , { - readSemaphore = CreateSemaphoreA(0, FileLockSemMax, FileLockSemMax, readSemName.toLocal8Bit()); - } ); + readSemaphore = CreateSemaphore(0, FileLockSemMax, FileLockSemMax, reinterpret_cast(readSemName.utf16())); if (readSemaphore) { for (int i = 0; i < numReadLocks; ++i) diff --git a/src/corelib/io/qsettings_win.cpp b/src/corelib/io/qsettings_win.cpp index 0cbcc10..1e1509d 100644 --- a/src/corelib/io/qsettings_win.cpp +++ b/src/corelib/io/qsettings_win.cpp @@ -130,24 +130,13 @@ static void mergeKeySets(NameSet *dest, const QStringList &src) static QString errorCodeToString(DWORD errorCode) { - QString result; - QT_WA({ - wchar_t *data = 0; - FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, - 0, errorCode, 0, - data, 0, 0); - result = QString::fromUtf16(reinterpret_cast (data)); - if (data != 0) - LocalFree(data); - }, { - char *data = 0; - FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, - 0, errorCode, 0, - (char *)&data, 0, 0); - result = QString::fromLocal8Bit(data); - if (data != 0) - LocalFree(data); - }) + wchar_t *data = 0; + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, 0, errorCode, 0, data, 0, 0); + QString result = QString::fromWCharArray(data); + + if (data != 0) + LocalFree(data); + if (result.endsWith(QLatin1Char('\n'))) result.truncate(result.length() - 1); @@ -158,15 +147,8 @@ static QString errorCodeToString(DWORD errorCode) static HKEY openKey(HKEY parentHandle, REGSAM perms, const QString &rSubKey) { HKEY resultHandle = 0; - - LONG res; - QT_WA( { - res = RegOpenKeyExW(parentHandle, reinterpret_cast(rSubKey.utf16()), - 0, perms, &resultHandle); - } , { - res = RegOpenKeyExA(parentHandle, rSubKey.toLocal8Bit(), + LONG res = RegOpenKeyEx(parentHandle, reinterpret_cast(rSubKey.utf16()), 0, perms, &resultHandle); - } ); if (res == ERROR_SUCCESS) return resultHandle; @@ -183,14 +165,8 @@ static HKEY createOrOpenKey(HKEY parentHandle, REGSAM perms, const QString &rSub return resultHandle; // try to create it - LONG res; - QT_WA( { - res = RegCreateKeyExW(parentHandle, reinterpret_cast(rSubKey.utf16()), 0, 0, - REG_OPTION_NON_VOLATILE, perms, 0, &resultHandle, 0); - } , { - res = RegCreateKeyExA(parentHandle, rSubKey.toLocal8Bit(), 0, 0, + LONG res = RegCreateKeyEx(parentHandle, reinterpret_cast(rSubKey.utf16()), 0, 0, REG_OPTION_NON_VOLATILE, perms, 0, &resultHandle, 0); - } ); if (res == ERROR_SUCCESS) return resultHandle; @@ -225,20 +201,14 @@ static HKEY createOrOpenKey(HKEY parentHandle, const QString &rSubKey, bool *rea static QStringList childKeysOrGroups(HKEY parentHandle, QSettingsPrivate::ChildSpec spec) { QStringList result; - LONG res; DWORD numKeys; DWORD maxKeySize; DWORD numSubgroups; DWORD maxSubgroupSize; // Find the number of keys and subgroups, as well as the max of their lengths. - QT_WA( { - res = RegQueryInfoKeyW(parentHandle, 0, 0, 0, &numSubgroups, &maxSubgroupSize, 0, + LONG res = RegQueryInfoKey(parentHandle, 0, 0, 0, &numSubgroups, &maxSubgroupSize, 0, &numKeys, &maxKeySize, 0, 0, 0); - }, { - res = RegQueryInfoKeyA(parentHandle, 0, 0, 0, &numSubgroups, &maxSubgroupSize, 0, - &numKeys, &maxKeySize, 0, 0, 0); - } ); if (res != ERROR_SUCCESS) { qWarning("QSettings: RegQueryInfoKey() failed: %s", errorCodeToString(res).toLatin1().data()); @@ -258,36 +228,21 @@ static QStringList childKeysOrGroups(HKEY parentHandle, QSettingsPrivate::ChildS m = maxSubgroupSize; } - /* Windows NT/2000/XP: The size does not include the terminating null character. - Windows Me/98/95: The size includes the terminating null character. */ + /* The size does not include the terminating null character. */ ++m; // Get the list - QByteArray buff(m*sizeof(ushort), 0); + QByteArray buff(m * sizeof(wchar_t), 0); for (int i = 0; i < n; ++i) { QString item; - QT_WA( { - DWORD l = buff.size() / sizeof(ushort); - if (spec == QSettingsPrivate::ChildKeys) { - res = RegEnumValueW(parentHandle, i, - reinterpret_cast(buff.data()), - &l, 0, 0, 0, 0); - } else { - res = RegEnumKeyExW(parentHandle, i, - reinterpret_cast(buff.data()), - &l, 0, 0, 0, 0); - } - if (res == ERROR_SUCCESS) - item = QString::fromUtf16(reinterpret_cast(buff.data()), l); - }, { - DWORD l = buff.size(); - if (spec == QSettingsPrivate::ChildKeys) - res = RegEnumValueA(parentHandle, i, buff.data(), &l, 0, 0, 0, 0); - else - res = RegEnumKeyExA(parentHandle, i, buff.data(), &l, 0, 0, 0, 0); - if (res == ERROR_SUCCESS) - item = QString::fromLocal8Bit(buff.data(), l); - } ); + DWORD l = buff.size() / sizeof(wchar_t); + if (spec == QSettingsPrivate::ChildKeys) { + res = RegEnumValue(parentHandle, i, reinterpret_cast(buff.data()), &l, 0, 0, 0, 0); + } else { + res = RegEnumKeyEx(parentHandle, i, reinterpret_cast(buff.data()), &l, 0, 0, 0, 0); + } + if (res == ERROR_SUCCESS) + item = QString::fromWCharArray((const wchar_t *)buff.constData(), l); if (res != ERROR_SUCCESS) { qWarning("QSettings: RegEnumValue failed: %s", errorCodeToString(res).toLatin1().data()); @@ -342,12 +297,7 @@ static void deleteChildGroups(HKEY parentHandle) RegCloseKey(childGroupHandle); // delete group itself - LONG res; - QT_WA( { - res = RegDeleteKeyW(parentHandle, reinterpret_cast(group.utf16())); - }, { - res = RegDeleteKeyA(parentHandle, group.toLocal8Bit()); - } ); + LONG res = RegDeleteKey(parentHandle, reinterpret_cast(group.utf16())); if (res != ERROR_SUCCESS) { qWarning("QSettings: RegDeleteKey failed on subkey \"%s\": %s", group.toLatin1().data(), errorCodeToString(res).toLatin1().data()); @@ -519,12 +469,7 @@ bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVa // get the size and type of the value DWORD dataType; DWORD dataSize; - LONG res; - QT_WA( { - res = RegQueryValueExW(handle, reinterpret_cast(rSubkeyName.utf16()), 0, &dataType, 0, &dataSize); - }, { - res = RegQueryValueExA(handle, rSubkeyName.toLocal8Bit(), 0, &dataType, 0, &dataSize); - } ); + LONG res = RegQueryValueEx(handle, reinterpret_cast(rSubkeyName.utf16()), 0, &dataType, 0, &dataSize); if (res != ERROR_SUCCESS) { RegCloseKey(handle); return false; @@ -532,13 +477,8 @@ bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVa // get the value QByteArray data(dataSize, 0); - QT_WA( { - res = RegQueryValueExW(handle, reinterpret_cast(rSubkeyName.utf16()), 0, 0, - reinterpret_cast(data.data()), &dataSize); - }, { - res = RegQueryValueExA(handle, rSubkeyName.toLocal8Bit(), 0, 0, - reinterpret_cast(data.data()), &dataSize); - } ); + res = RegQueryValueEx(handle, reinterpret_cast(rSubkeyName.utf16()), 0, 0, + reinterpret_cast(data.data()), &dataSize); if (res != ERROR_SUCCESS) { RegCloseKey(handle); return false; @@ -549,11 +489,7 @@ bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVa case REG_SZ: { QString s; if (dataSize) { - QT_WA( { - s = QString::fromUtf16(((const ushort*)data.constData())); - }, { - s = QString::fromLocal8Bit(data.constData()); - } ); + s = QString::fromWCharArray(((const wchar_t *)data.constData())); } if (value != 0) *value = stringToVariant(s); @@ -565,12 +501,7 @@ bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVa if (dataSize) { int i = 0; for (;;) { - QString s; - QT_WA( { - s = QString::fromUtf16((const ushort*)data.constData() + i); - }, { - s = QString::fromLocal8Bit(data.constData() + i); - } ); + QString s = QString::fromWCharArray((const wchar_t *)data.constData() + i); i += s.length() + 1; if (s.isEmpty()) @@ -587,11 +518,7 @@ bool QWinSettingsPrivate::readKey(HKEY parentHandle, const QString &rSubKey, QVa case REG_BINARY: { QString s; if (dataSize) { - QT_WA( { - s = QString::fromUtf16((const ushort*)data.constData(), data.size()/2); - }, { - s = QString::fromLocal8Bit(data.constData(), data.size()); - } ); + s = QString::fromWCharArray((const wchar_t *)data.constData(), data.size() / 2); } if (value != 0) *value = stringToVariant(s); @@ -635,13 +562,8 @@ QWinSettingsPrivate::~QWinSettingsPrivate() #if defined(Q_OS_WINCE) remove(regList.at(0).key()); #else - DWORD res; QString emptyKey; - QT_WA( { - res = RegDeleteKeyW(writeHandle(), reinterpret_cast(emptyKey.utf16())); - }, { - res = RegDeleteKeyA(writeHandle(), emptyKey.toLocal8Bit()); - } ); + DWORD res = RegDeleteKey(writeHandle(), reinterpret_cast(emptyKey.utf16())); if (res != ERROR_SUCCESS) { qWarning("QSettings: Failed to delete key \"%s\": %s", regList.at(0).key().toLatin1().data(), errorCodeToString(res).toLatin1().data()); @@ -666,11 +588,7 @@ void QWinSettingsPrivate::remove(const QString &uKey) LONG res; HKEY handle = openKey(writeHandle(), registryPermissions, keyPath(rKey)); if (handle != 0) { - QT_WA( { - res = RegDeleteValueW(handle, reinterpret_cast(keyName(rKey).utf16())); - }, { - res = RegDeleteValueA(handle, keyName(rKey).toLocal8Bit()); - } ); + res = RegDeleteValue(handle, reinterpret_cast(keyName(rKey).utf16())); RegCloseKey(handle); } @@ -685,12 +603,7 @@ void QWinSettingsPrivate::remove(const QString &uKey) for (int i = 0; i < childKeys.size(); ++i) { QString group = childKeys.at(i); - LONG res; - QT_WA( { - res = RegDeleteValueW(handle, reinterpret_cast(group.utf16())); - }, { - res = RegDeleteValueA(handle, group.toLocal8Bit()); - } ); + LONG res = RegDeleteValue(handle, reinterpret_cast(group.utf16())); if (res != ERROR_SUCCESS) { qWarning("QSettings: RegDeleteValue failed on subkey \"%s\": %s", group.toLatin1().data(), errorCodeToString(res).toLatin1().data()); @@ -701,11 +614,7 @@ void QWinSettingsPrivate::remove(const QString &uKey) // For WinCE always Close the handle first. RegCloseKey(handle); #endif - QT_WA( { - res = RegDeleteKeyW(writeHandle(), reinterpret_cast(rKey.utf16())); - }, { - res = RegDeleteKeyA(writeHandle(), rKey.toLocal8Bit()); - } ); + res = RegDeleteKey(writeHandle(), reinterpret_cast(rKey.utf16())); if (res != ERROR_SUCCESS) { qWarning("QSettings: RegDeleteKey failed on key \"%s\": %s", @@ -761,27 +670,15 @@ void QWinSettingsPrivate::set(const QString &uKey, const QVariant &value) if (type == REG_BINARY) { QString s = variantToString(value); - QT_WA( { - regValueBuff = QByteArray((const char*)s.utf16(), s.length()*2); - }, { - regValueBuff = QByteArray((const char*)s.toLocal8Bit(), s.length()); - } ); + regValueBuff = QByteArray((const char*)s.utf16(), s.length() * 2); } else { QStringList::const_iterator it = l.constBegin(); for (; it != l.constEnd(); ++it) { const QString &s = *it; - QT_WA( { - regValueBuff += QByteArray((const char*)s.utf16(), (s.length() + 1)*2); - }, { - regValueBuff += QByteArray((const char*)s.toLocal8Bit(), s.length() + 1); - } ); + regValueBuff += QByteArray((const char*)s.utf16(), (s.length() + 1) * 2); } - QT_WA( { - regValueBuff.append((char)0); - regValueBuff.append((char)0); - }, { - regValueBuff.append((char)0); - } ); + regValueBuff.append((char)0); + regValueBuff.append((char)0); } break; } @@ -794,21 +691,6 @@ void QWinSettingsPrivate::set(const QString &uKey, const QVariant &value) } case QVariant::ByteArray: - // On Win95/98/Me QString::toLocal8Bit() fails to handle chars > 0x7F. So we don't go through variantToString() at all. - if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) { - QByteArray ba = value.toByteArray(); - regValueBuff = "@ByteArray("; - regValueBuff += ba; - regValueBuff += ')'; - if (ba.contains('\0')) { - type = REG_BINARY; - } else { - type = REG_SZ; - regValueBuff += '\0'; - } - - break; - } // fallthrough intended default: { @@ -817,33 +699,18 @@ void QWinSettingsPrivate::set(const QString &uKey, const QVariant &value) QString s = variantToString(value); type = stringContainsNullChar(s) ? REG_BINARY : REG_SZ; if (type == REG_BINARY) { - QT_WA( { - regValueBuff = QByteArray((const char*)s.utf16(), s.length()*2); - }, { - regValueBuff = QByteArray((const char*)s.toLocal8Bit(), s.length()); - } ); + regValueBuff = QByteArray((const char*)s.utf16(), s.length() * 2); } else { - QT_WA( { - regValueBuff = QByteArray((const char*)s.utf16(), (s.length() + 1)*2); - }, { - regValueBuff = QByteArray((const char*)s.toLocal8Bit(), s.length() + 1); - } ); + regValueBuff = QByteArray((const char*)s.utf16(), (s.length() + 1) * 2); } break; } } // set the value - LONG res; - QT_WA( { - res = RegSetValueExW(handle, reinterpret_cast(keyName(rKey).utf16()), 0, type, - reinterpret_cast(regValueBuff.constData()), - regValueBuff.size()); - }, { - res = RegSetValueExA(handle, keyName(rKey).toLocal8Bit(), 0, type, + LONG res = RegSetValueEx(handle, reinterpret_cast(keyName(rKey).utf16()), 0, type, reinterpret_cast(regValueBuff.constData()), regValueBuff.size()); - } ); if (res == ERROR_SUCCESS) { deleteWriteHandleOnExit = false; diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index e6a471c..f0a3fec 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -1742,18 +1742,10 @@ QString QCoreApplication::applicationFilePath() return d->cachedApplicationFilePath; #if defined( Q_WS_WIN ) - QFileInfo filePath; - QT_WA({ - wchar_t module_name[MAX_PATH+1]; - GetModuleFileNameW(0, module_name, MAX_PATH); - module_name[MAX_PATH] = 0; - filePath = QString::fromUtf16((ushort *)module_name); - }, { - char module_name[MAX_PATH+1]; - GetModuleFileNameA(0, module_name, MAX_PATH); - module_name[MAX_PATH] = 0; - filePath = QString::fromLocal8Bit(module_name); - }); + wchar_t module_name[MAX_PATH]; + GetModuleFileName(0, module_name, MAX_PATH); + module_name[MAX_PATH] = 0; + QFileInfo filePath = QString::fromWCharArray(module_name); d->cachedApplicationFilePath = filePath.filePath(); return d->cachedApplicationFilePath; @@ -1902,13 +1894,13 @@ QStringList QCoreApplication::arguments() return list; } #ifdef Q_OS_WIN - QString cmdline = QT_WA_INLINE(QString::fromUtf16((unsigned short *)GetCommandLineW()), QString::fromLocal8Bit(GetCommandLineA())); + QString cmdline = QString::fromWCharArray(GetCommandLine()); #if defined(Q_OS_WINCE) wchar_t tempFilename[MAX_PATH+1]; - if (GetModuleFileNameW(0, tempFilename, MAX_PATH)) { + if (GetModuleFileName(0, tempFilename, MAX_PATH)) { tempFilename[MAX_PATH] = 0; - cmdline.prepend(QLatin1Char('\"') + QString::fromUtf16((unsigned short *)tempFilename) + QLatin1String("\" ")); + cmdline.prepend(QLatin1Char('\"') + QString::fromWCharArray(tempFilename) + QLatin1String("\" ")); } #endif // Q_OS_WINCE diff --git a/src/corelib/kernel/qcoreapplication_win.cpp b/src/corelib/kernel/qcoreapplication_win.cpp index 7a35340..657abd1 100644 --- a/src/corelib/kernel/qcoreapplication_win.cpp +++ b/src/corelib/kernel/qcoreapplication_win.cpp @@ -45,14 +45,15 @@ #include "qt_windows.h" #include "qvector.h" #include "qmutex.h" +#include "qfileinfo.h" #include "qcorecmdlineargs_p.h" #include #include QT_BEGIN_NAMESPACE -char appFileName[MAX_PATH+1]; // application file name -char theAppName[MAX_PATH+1]; // application name +char appFileName[MAX_PATH]; // application file name +char theAppName[MAX_PATH]; // application name HINSTANCE appInst = 0; // handle to app instance HINSTANCE appPrevInst = 0; // handle to prev app instance int appCmdShow = 0; @@ -73,48 +74,35 @@ Q_CORE_EXPORT int qWinAppCmdShow() // get main window sho return appCmdShow; } +Q_CORE_EXPORT QString qAppFileName() // get application file name +{ + wchar_t buffer[MAX_PATH]; + GetModuleFileName(0, buffer, MAX_PATH); + return QString::fromWCharArray(buffer); +} void set_winapp_name() { static bool already_set = false; if (!already_set) { already_set = true; -#ifndef Q_OS_WINCE - GetModuleFileNameA(0, appFileName, sizeof(appFileName)); - appFileName[sizeof(appFileName)-1] = 0; -#else - QString afm; - afm.resize(sizeof(appFileName)); - afm.resize(GetModuleFileName(0, (wchar_t *) (afm.unicode()), sizeof(appFileName))); - memcpy(appFileName, afm.toLatin1(), sizeof(appFileName)); -#endif - const char *p = strrchr(appFileName, '\\'); // skip path - if (p) - memcpy(theAppName, p+1, qstrlen(p)); - int l = qstrlen(theAppName); - if ((l > 4) && !qstricmp(theAppName + l - 4, ".exe")) - theAppName[l-4] = '\0'; // drop .exe extension - if (appInst == 0) { - QT_WA({ - appInst = GetModuleHandle(0); - }, { - appInst = GetModuleHandleA(0); - }); - } - } -} + QString moduleName = qAppFileName(); -Q_CORE_EXPORT QString qAppFileName() // get application file name -{ - return QString::fromLatin1(appFileName); + QByteArray filePath = moduleName.toLocal8Bit(); + QByteArray fileName = QFileInfo(moduleName).baseName().toLocal8Bit(); + + memcpy(appFileName, filePath.constData(), filePath.length()); + memcpy(theAppName, fileName.constData(), fileName.length()); + + if (appInst == 0) + appInst = GetModuleHandle(0); + } } QString QCoreApplicationPrivate::appName() const { - if (!theAppName[0]) - set_winapp_name(); - return QString::fromLatin1(theAppName); + return QFileInfo(qAppFileName()).baseName(); } class QWinMsgHandlerCriticalSection @@ -145,15 +133,11 @@ Q_CORE_EXPORT void qWinMsgHandler(QtMsgType t, const char* str) str = "(null)"; staticCriticalSection.lock(); - QT_WA({ - QString s(QString::fromLocal8Bit(str)); - s += QLatin1Char('\n'); - OutputDebugStringW((TCHAR*)s.utf16()); - }, { - QByteArray s(str); - s += '\n'; - OutputDebugStringA(s.data()); - }) + + QString s(QString::fromLocal8Bit(str)); + s += QLatin1Char('\n'); + OutputDebugString((wchar_t*)s.utf16()); + staticCriticalSection.unlock(); } diff --git a/src/corelib/kernel/qcorecmdlineargs_p.h b/src/corelib/kernel/qcorecmdlineargs_p.h index c0dd813..a012b4e 100644 --- a/src/corelib/kernel/qcorecmdlineargs_p.h +++ b/src/corelib/kernel/qcorecmdlineargs_p.h @@ -135,9 +135,9 @@ static inline QStringList qWinCmdArgs(QString cmdLine) // not const-ref: this mi QStringList args; int argc = 0; - QVector argv = qWinCmdLine((ushort*)cmdLine.utf16(), cmdLine.length(), argc); + QVector argv = qWinCmdLine((wchar_t *)cmdLine.utf16(), cmdLine.length(), argc); for (int a = 0; a < argc; ++a) { - args << QString::fromUtf16(argv[a]); + args << QString::fromWCharArray(argv[a]); } return args; @@ -147,10 +147,7 @@ static inline QStringList qCmdLineArgs(int argc, char *argv[]) { Q_UNUSED(argc) Q_UNUSED(argv) - QString cmdLine = QT_WA_INLINE( - QString::fromUtf16((unsigned short*)GetCommandLineW()), - QString::fromLocal8Bit(GetCommandLineA()) - ); + QString cmdLine = QString::fromWCharArray(GetCommandLine()); return qWinCmdArgs(cmdLine); } diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index cb1549c..23e4fa9 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -355,8 +355,7 @@ QEventDispatcherWin32Private::QEventDispatcherWin32Private() { resolveTimerAPI(); - wakeUpNotifier.setHandle(QT_WA_INLINE(CreateEventW(0, FALSE, FALSE, 0), - CreateEventA(0, FALSE, FALSE, 0))); + wakeUpNotifier.setHandle(CreateEvent(0, FALSE, FALSE, 0)); if (!wakeUpNotifier.handle()) qWarning("QEventDispatcher: Creating QEventDispatcherWin32Private wakeup event failed"); } @@ -367,13 +366,8 @@ QEventDispatcherWin32Private::~QEventDispatcherWin32Private() CloseHandle(wakeUpNotifier.handle()); if (internalHwnd) DestroyWindow(internalHwnd); - QByteArray className = "QEventDispatcherWin32_Internal_Widget" + QByteArray::number(quintptr(qt_internal_proc)); -#if !defined(Q_OS_WINCE) - UnregisterClassA(className.constData(), qWinAppInst()); -#else - UnregisterClassW(reinterpret_cast (QString::fromLatin1(className.constData()).utf16()) - , qWinAppInst()); -#endif + QString className = QLatin1String("QEventDispatcherWin32_Internal_Widget") + QString::number(quintptr(qt_internal_proc)); + UnregisterClass((wchar_t*)className.utf16(), qWinAppInst()); } void QEventDispatcherWin32Private::activateEventNotifier(QWinEventNotifier * wen) @@ -382,18 +376,24 @@ void QEventDispatcherWin32Private::activateEventNotifier(QWinEventNotifier * wen QCoreApplication::sendEvent(wen, &event); } - +// ### Qt 5: remove Q_CORE_EXPORT bool winPeekMessage(MSG* msg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg) { - QT_WA({ return PeekMessage(msg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg); } , - { return PeekMessageA(msg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg); }); + return PeekMessage(msg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg); } +// ### Qt 5: remove Q_CORE_EXPORT bool winPostMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { - QT_WA({ return PostMessage(hWnd, msg, wParam, lParam); } , - { return PostMessageA(hWnd, msg, wParam, lParam); }); + return PostMessage(hWnd, msg, wParam, lParam); +} + +// ### Qt 5: remove +Q_CORE_EXPORT bool winGetMessage(MSG* msg, HWND hWnd, UINT wMsgFilterMin, + UINT wMsgFilterMax) +{ + return GetMessage(msg, hWnd, wMsgFilterMin, wMsgFilterMax); } // This function is called by a workerthread @@ -443,10 +443,10 @@ LRESULT CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp) #ifdef GWLP_USERDATA QEventDispatcherWin32 *eventDispatcher = - (QEventDispatcherWin32 *) GetWindowLongPtrA(hwnd, GWLP_USERDATA); + (QEventDispatcherWin32 *) GetWindowLongPtr(hwnd, GWLP_USERDATA); #else QEventDispatcherWin32 *eventDispatcher = - (QEventDispatcherWin32 *) GetWindowLongA(hwnd, GWL_USERDATA); + (QEventDispatcherWin32 *) GetWindowLong(hwnd, GWL_USERDATA); #endif if (eventDispatcher) { QEventDispatcherWin32Private *d = eventDispatcher->d_func(); @@ -494,54 +494,35 @@ LRESULT CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp) static HWND qt_create_internal_window(const QEventDispatcherWin32 *eventDispatcher) { - HINSTANCE hi = qWinAppInst(); -#if defined(Q_OS_WINCE) + // make sure that multiple Qt's can coexist in the same process + QString className = QLatin1Strign("QEventDispatcherWin32_Internal_Widget") + QString::number(quintptr(qt_internal_proc)); + WNDCLASS wc; -#else - WNDCLASSA wc; -#endif wc.style = 0; wc.lpfnWndProc = qt_internal_proc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; - wc.hInstance = hi; + wc.hInstance = qWinAppInst(); wc.hIcon = 0; wc.hCursor = 0; wc.hbrBackground = 0; wc.lpszMenuName = NULL; + wc.lpszClassName = reinterpret_cast (className.utf16()); - // make sure that multiple Qt's can coexist in the same process - QByteArray className = "QEventDispatcherWin32_Internal_Widget" + QByteArray::number(quintptr(qt_internal_proc)); -#if defined(Q_OS_WINCE) - QString tmp = QString::fromLatin1(className.data()); - wc.lpszClassName = reinterpret_cast (tmp.utf16()); RegisterClass(&wc); HWND wnd = CreateWindow(wc.lpszClassName, // classname - wc.lpszClassName, // window name - 0, // style - 0, 0, 0, 0, // geometry - 0, // parent - 0, // menu handle - hi, // application - 0); // windows creation data. -#else - wc.lpszClassName = className.constData(); - RegisterClassA(&wc); - HWND wnd = CreateWindowA(wc.lpszClassName, // classname - wc.lpszClassName, // window name - 0, // style - 0, 0, 0, 0, // geometry - 0, // parent - 0, // menu handle - hi, // application - 0); // windows creation data. -#endif - + wc.lpszClassName, // window name + 0, // style + 0, 0, 0, 0, // geometry + 0, // parent + 0, // menu handle + qWinAppInst(), // application + 0); // windows creation data. #ifdef GWLP_USERDATA - SetWindowLongPtrA(wnd, GWLP_USERDATA, (LONG_PTR)eventDispatcher); + SetWindowLongPtr(wnd, GWLP_USERDATA, (LONG_PTR)eventDispatcher); #else - SetWindowLongA(wnd, GWL_USERDATA, (LONG)eventDispatcher); + SetWindowLong(wnd, GWL_USERDATA, (LONG)eventDispatcher); #endif if (!wnd) { @@ -690,7 +671,7 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags) haveMessage = true; msg = d->queuedSocketEvents.takeFirst(); } else { - haveMessage = winPeekMessage(&msg, 0, 0, 0, PM_REMOVE); + haveMessage = PeekMessage(&msg, 0, 0, 0, PM_REMOVE); if (haveMessage && (flags & QEventLoop::ExcludeUserInputEvents) && ((msg.message >= WM_KEYFIRST && msg.message <= WM_KEYLAST) @@ -738,11 +719,7 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags) if (!filterEvent(&msg)) { TranslateMessage(&msg); - QT_WA({ - DispatchMessage(&msg); - } , { - DispatchMessageA(&msg); - }); + DispatchMessage(&msg); } } else if (waitRet >= WAIT_OBJECT_0 && waitRet < WAIT_OBJECT_0 + nCount) { d->activateEventNotifier(d->winEventNotifierList.at(waitRet - WAIT_OBJECT_0)); @@ -781,7 +758,7 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags) bool QEventDispatcherWin32::hasPendingEvents() { MSG msg; - return qGlobalPostedEventsCount() || winPeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE); + return qGlobalPostedEventsCount() || PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE); } void QEventDispatcherWin32::registerSocketNotifier(QSocketNotifier *notifier) diff --git a/src/corelib/kernel/qfunctions_wince.cpp b/src/corelib/kernel/qfunctions_wince.cpp index 2c47adb..5680ad5 100644 --- a/src/corelib/kernel/qfunctions_wince.cpp +++ b/src/corelib/kernel/qfunctions_wince.cpp @@ -108,7 +108,7 @@ int qt_wince__getdrive( void ) return 1; } -int qt_wince__waccess( const WCHAR *path, int pmode ) +int qt_wince__waccess( const wchar_t *path, int pmode ) { DWORD res = GetFileAttributes( path ); if ( 0xFFFFFFFF == res ) @@ -118,7 +118,7 @@ int qt_wince__waccess( const WCHAR *path, int pmode ) return -1; if ( (pmode & X_OK) && !(res & FILE_ATTRIBUTE_DIRECTORY) ) { - QString file = QString::fromUtf16(reinterpret_cast (path)); + QString file = QString::fromWCharArray(path); if ( !(file.endsWith(QString::fromLatin1(".exe")) || file.endsWith(QString::fromLatin1(".com"))) ) return -1; @@ -130,12 +130,12 @@ int qt_wince__waccess( const WCHAR *path, int pmode ) int qt_wince_open( const char *filename, int oflag, int pmode ) { QString fn( QString::fromLatin1(filename) ); - return _wopen( (WCHAR*)fn.utf16(), oflag, pmode ); + return _wopen( (wchar_t*)fn.utf16(), oflag, pmode ); } -int qt_wince__wopen( const WCHAR *filename, int oflag, int /*pmode*/ ) +int qt_wince__wopen( const wchar_t *filename, int oflag, int /*pmode*/ ) { - WCHAR *flag; + wchar_t *flag; if ( oflag & _O_APPEND ) { if ( oflag & _O_WRONLY ) { @@ -290,7 +290,7 @@ bool qt_wince__chmod(const char *file, int mode) return _wchmod( reinterpret_cast (QString::fromLatin1(file).utf16()), mode); } -bool qt_wince__wchmod(const WCHAR *file, int mode) +bool qt_wince__wchmod(const wchar_t *file, int mode) { // ### Does not work properly, what about just adding one property? if(mode&_S_IWRITE) { diff --git a/src/corelib/kernel/qfunctions_wince.h b/src/corelib/kernel/qfunctions_wince.h index 307e17b..41cb641 100644 --- a/src/corelib/kernel/qfunctions_wince.h +++ b/src/corelib/kernel/qfunctions_wince.h @@ -175,8 +175,8 @@ typedef int mode_t; extern int errno; int qt_wince__getdrive( void ); -int qt_wince__waccess( const WCHAR *path, int pmode ); -int qt_wince__wopen( const WCHAR *filename, int oflag, int pmode ); +int qt_wince__waccess( const wchar_t *path, int pmode ); +int qt_wince__wopen( const wchar_t *filename, int oflag, int pmode ); long qt_wince__lseek( int handle, long offset, int origin ); int qt_wince__read( int handle, void *buffer, unsigned int count ); int qt_wince__write( int handle, const void *buffer, unsigned int count ); @@ -204,7 +204,7 @@ int qt_wince_SetErrorMode(int); #endif bool qt_wince__chmod(const char *file, int mode); -bool qt_wince__wchmod(const WCHAR *file, int mode); +bool qt_wince__wchmod(const wchar_t *file, int mode); #pragma warning(disable: 4273) HANDLE qt_wince_CreateFileA(LPCSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE); diff --git a/src/corelib/kernel/qsharedmemory_win.cpp b/src/corelib/kernel/qsharedmemory_win.cpp index d963a6d..c88149a 100644 --- a/src/corelib/kernel/qsharedmemory_win.cpp +++ b/src/corelib/kernel/qsharedmemory_win.cpp @@ -106,16 +106,11 @@ HANDLE QSharedMemoryPrivate::handle() return false; } #ifndef Q_OS_WINCE - QT_WA({ - hand = OpenFileMappingW(FILE_MAP_ALL_ACCESS, false, (TCHAR*)safeKey.utf16()); - }, { - hand = OpenFileMappingA(FILE_MAP_ALL_ACCESS, false, safeKey.toLocal8Bit().constData()); - }); + hand = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, (wchar_t*)safeKey.utf16()); #else // This works for opening a mapping too, but always opens it with read/write access in // attach as it seems. - hand = CreateFileMappingW(INVALID_HANDLE_VALUE, - 0, PAGE_READWRITE, 0, 0, (TCHAR*)safeKey.utf16()); + hand = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, 0, (wchar_t*)safeKey.utf16()); #endif if (!hand) { setErrorString(function); @@ -148,13 +143,7 @@ bool QSharedMemoryPrivate::create(int size) } // Create the file mapping. - QT_WA( { - hand = CreateFileMappingW(INVALID_HANDLE_VALUE, - 0, PAGE_READWRITE, 0, size, (TCHAR*)safeKey.utf16()); - }, { - hand = CreateFileMappingA(INVALID_HANDLE_VALUE, - 0, PAGE_READWRITE, 0, size, safeKey.toLocal8Bit().constData()); - } ); + hand = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, size, (wchar_t*)safeKey.utf16()); setErrorString(function); // hand is valid when it already exists unlike unix so explicitly check diff --git a/src/corelib/kernel/qsystemsemaphore_win.cpp b/src/corelib/kernel/qsystemsemaphore_win.cpp index 4e03ddf..1102258 100644 --- a/src/corelib/kernel/qsystemsemaphore_win.cpp +++ b/src/corelib/kernel/qsystemsemaphore_win.cpp @@ -87,11 +87,7 @@ HANDLE QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode) // Create it if it doesn't already exists. if (semaphore == 0) { QString safeName = makeKeyFileName(); - QT_WA({ - semaphore = CreateSemaphoreW(0, initialValue, MAXLONG, (TCHAR*)safeName.utf16()); - }, { - semaphore = CreateSemaphoreA(0, initialValue, MAXLONG, safeName.toLocal8Bit().constData()); - }); + semaphore = CreateSemaphore(0, initialValue, MAXLONG, (wchar_t*)safeName.utf16()); if (semaphore == NULL) setErrorString(QLatin1String("QSystemSemaphore::handle")); } diff --git a/src/corelib/kernel/qtimer.cpp b/src/corelib/kernel/qtimer.cpp index d2a0b3a..2ee9d26 100644 --- a/src/corelib/kernel/qtimer.cpp +++ b/src/corelib/kernel/qtimer.cpp @@ -103,9 +103,8 @@ QT_BEGIN_NAMESPACE Note that QTimer's accuracy depends on the underlying operating system and hardware. Most platforms support an accuracy of - 1 millisecond, but Windows 98 supports only 55. If Qt is - unable to deliver the requested number of timer clicks, it will - silently discard some. + 1 millisecond. If Qt is unable to deliver the requested number of + timer clicks, it will silently discard some. An alternative to using QTimer is to call QObject::startTimer() for your object and reimplement the QObject::timerEvent() event diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp index 4d465dc..8f364ba 100644 --- a/src/corelib/plugin/qlibrary.cpp +++ b/src/corelib/plugin/qlibrary.cpp @@ -623,11 +623,7 @@ bool QLibraryPrivate::isPlugin(QSettings *settings) #endif if (!pHnd) { #ifdef Q_OS_WIN - QT_WA({ - hTempModule = ::LoadLibraryExW((wchar_t*)QDir::toNativeSeparators(fileName).utf16(), 0, DONT_RESOLVE_DLL_REFERENCES); - } , { - temporary_load = load_sys(); - }); + hTempModule = ::LoadLibraryEx((wchar_t*)QDir::toNativeSeparators(fileName).utf16(), 0, DONT_RESOLVE_DLL_REFERENCES); #else temporary_load = load_sys(); #endif @@ -641,7 +637,7 @@ bool QLibraryPrivate::isPlugin(QSettings *settings) QtPluginQueryVerificationDataFunction qtPluginQueryVerificationDataFunction = hTempModule ? (QtPluginQueryVerificationDataFunction) #ifdef Q_OS_WINCE - ::GetProcAddressW(hTempModule, L"qt_plugin_query_verification_data") + ::GetProcAddress(hTempModule, L"qt_plugin_query_verification_data") #else ::GetProcAddress(hTempModule, "qt_plugin_query_verification_data") #endif diff --git a/src/corelib/plugin/qlibrary_win.cpp b/src/corelib/plugin/qlibrary_win.cpp index 43eeafa..847c0d2 100644 --- a/src/corelib/plugin/qlibrary_win.cpp +++ b/src/corelib/plugin/qlibrary_win.cpp @@ -67,30 +67,18 @@ bool QLibraryPrivate::load_sys() //avoid 'Bad Image' message box UINT oldmode = SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX); - QT_WA({ - pHnd = LoadLibraryW((TCHAR*)QDir::toNativeSeparators(attempt).utf16()); - } , { - pHnd = LoadLibraryA(QFile::encodeName(QDir::toNativeSeparators(attempt)).data()); - }); - + pHnd = LoadLibrary((wchar_t*)QDir::toNativeSeparators(attempt).utf16()); + if (pluginState != IsAPlugin) { #if defined(Q_OS_WINCE) if (!pHnd && ::GetLastError() == ERROR_MOD_NOT_FOUND) { QString secondAttempt = fileName; - QT_WA({ - pHnd = LoadLibraryW((TCHAR*)QDir::toNativeSeparators(secondAttempt).utf16()); - } , { - pHnd = LoadLibraryA(QFile::encodeName(QDir::toNativeSeparators(secondAttempt)).data()); - }); + pHnd = LoadLibrary((wchar_t*)QDir::toNativeSeparators(secondAttempt).utf16()); } #endif if (!pHnd && ::GetLastError() == ERROR_MOD_NOT_FOUND) { attempt += QLatin1String(".dll"); - QT_WA({ - pHnd = LoadLibraryW((TCHAR*)QDir::toNativeSeparators(attempt).utf16()); - } , { - pHnd = LoadLibraryA(QFile::encodeName(QDir::toNativeSeparators(attempt)).data()); - }); + pHnd = LoadLibrary((wchar_t*)QDir::toNativeSeparators(attempt).utf16()); } } @@ -100,15 +88,11 @@ bool QLibraryPrivate::load_sys() } if (pHnd) { errorString.clear(); - QT_WA({ - TCHAR buffer[MAX_PATH + 1]; - ::GetModuleFileNameW(pHnd, buffer, MAX_PATH); - attempt = QString::fromUtf16(reinterpret_cast(&buffer)); - }, { - char buffer[MAX_PATH + 1]; - ::GetModuleFileNameA(pHnd, buffer, MAX_PATH); - attempt = QString::fromLocal8Bit(buffer); - }); + + wchar_t buffer[MAX_PATH]; + ::GetModuleFileName(pHnd, buffer, MAX_PATH); + attempt = QString::fromWCharArray(buffer); + const QDir dir = QFileInfo(fileName).dir(); const QString realfilename = attempt.mid(attempt.lastIndexOf(QLatin1Char('\\')) + 1); if (dir.path() == QLatin1String(".")) diff --git a/src/corelib/thread/qmutex_win.cpp b/src/corelib/thread/qmutex_win.cpp index f2022a5..1d247fc 100644 --- a/src/corelib/thread/qmutex_win.cpp +++ b/src/corelib/thread/qmutex_win.cpp @@ -50,19 +50,7 @@ QT_BEGIN_NAMESPACE QMutexPrivate::QMutexPrivate(QMutex::RecursionMode mode) : recursive(mode == QMutex::Recursive), contenders(0), lastSpinCount(0), owner(0), count(0) { - if (QSysInfo::WindowsVersion == 0) { - // mutex was created before initializing WindowsVersion. this - // can happen when creating the resource file engine handler, - // for example. try again with just the A version -#ifdef Q_OS_WINCE - event = CreateEventW(0, FALSE, FALSE, 0); -#else - event = CreateEventA(0, FALSE, FALSE, 0); -#endif - } else { - event = QT_WA_INLINE(CreateEventW(0, FALSE, FALSE, 0), - CreateEventA(0, FALSE, FALSE, 0)); - } + event = CreateEvent(0, FALSE, FALSE, 0); if (!event) qWarning("QMutexPrivate::QMutexPrivate: Cannot create event"); } diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp index b5bdba3..6c24784 100644 --- a/src/corelib/thread/qthread_win.cpp +++ b/src/corelib/thread/qthread_win.cpp @@ -163,8 +163,7 @@ void qt_watch_adopted_thread(const HANDLE adoptedThreadHandle, QThread *qthread) // Start watcher thread if it is not already running. if (qt_adopted_thread_watcher_handle == 0) { if (qt_adopted_thread_wakeup == 0) { - qt_adopted_thread_wakeup = QT_WA_INLINE(CreateEventW(0, false, false, 0), - CreateEventA(0, false, false, 0)); + qt_adopted_thread_wakeup = CreateEvent(0, false, false, 0); qt_adopted_thread_handles.prepend(qt_adopted_thread_wakeup); } @@ -364,11 +363,10 @@ int QThread::idealThreadCount() void QThread::yieldCurrentThread() { #ifndef Q_OS_WINCE - if (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based) - SwitchToThread(); - else + SwitchToThread(); +#else + ::Sleep(0); #endif - ::Sleep(0); } void QThread::sleep(unsigned long secs) @@ -419,17 +417,11 @@ void QThread::start(Priority priority) return; } - // Since Win 9x will have problems if the priority is idle or time critical - // we have to use the closest one instead int prio; d->priority = priority; switch (d->priority) { case IdlePriority: - if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) { - prio = THREAD_PRIORITY_LOWEST; - } else { - prio = THREAD_PRIORITY_IDLE; - } + prio = THREAD_PRIORITY_IDLE; break; case LowestPriority: @@ -453,11 +445,7 @@ void QThread::start(Priority priority) break; case TimeCriticalPriority: - if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) { - prio = THREAD_PRIORITY_HIGHEST; - } else { - prio = THREAD_PRIORITY_TIME_CRITICAL; - } + prio = THREAD_PRIORITY_TIME_CRITICAL; break; case InheritPriority: @@ -563,17 +551,11 @@ void QThread::setPriority(Priority priority) // copied from start() with a few modifications: - // Since Win 9x will have problems if the priority is idle or time critical - // we have to use the closest one instead int prio; d->priority = priority; switch (d->priority) { case IdlePriority: - if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) { - prio = THREAD_PRIORITY_LOWEST; - } else { - prio = THREAD_PRIORITY_IDLE; - } + prio = THREAD_PRIORITY_IDLE; break; case LowestPriority: @@ -597,11 +579,7 @@ void QThread::setPriority(Priority priority) break; case TimeCriticalPriority: - if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) { - prio = THREAD_PRIORITY_HIGHEST; - } else { - prio = THREAD_PRIORITY_TIME_CRITICAL; - } + prio = THREAD_PRIORITY_TIME_CRITICAL; break; case InheritPriority: diff --git a/src/corelib/thread/qwaitcondition_win.cpp b/src/corelib/thread/qwaitcondition_win.cpp index 9129fb6..b0146d2 100644 --- a/src/corelib/thread/qwaitcondition_win.cpp +++ b/src/corelib/thread/qwaitcondition_win.cpp @@ -64,11 +64,7 @@ class QWaitConditionEvent public: inline QWaitConditionEvent() : priority(0), wokenUp(false) { - QT_WA ({ - event = CreateEvent(NULL, TRUE, FALSE, NULL); - }, { - event = CreateEventA(NULL, TRUE, FALSE, NULL); - }); + event = CreateEvent(NULL, TRUE, FALSE, NULL); } inline ~QWaitConditionEvent() { CloseHandle(event); } int priority; diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index 6674717..42f4304 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -2503,16 +2503,9 @@ QString QDateTime::toString(Qt::DateFormat f) const buf += QLatin1Char(' '); buf += QString::number(d->date.day()); #else - QString winstr; - QT_WA({ - TCHAR out[255]; - GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_ILDATE, out, 255); - winstr = QString::fromUtf16((ushort*)out); - } , { - char out[255]; - GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_ILDATE, (char*)&out, 255); - winstr = QString::fromLocal8Bit(out); - }); + wchar_t out[255]; + GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_ILDATE, out, 255); + QString winstr = QString::fromWCharArray(out); switch (winstr.toInt()) { case 1: buf = d->date.shortDayName(d->date.dayOfWeek()); diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index 8c1a0ff..fef1931 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -386,15 +386,8 @@ static QString winIso3116CtryName(LCID id = LOCALE_USER_DEFAULT); static QString getWinLocaleInfo(LCTYPE type) { - int cnt = 0; - LCID id = GetUserDefaultLCID(); - - QT_WA({ - cnt = GetLocaleInfoW(id, type, 0, 0)*2; - } , { - cnt = GetLocaleInfoA(id, type, 0, 0); - }); + int cnt = GetLocaleInfo(id, type, 0, 0) * 2; if (cnt == 0) { qWarning("QLocale: empty windows locale info (%d)", (int)type); @@ -403,27 +396,14 @@ static QString getWinLocaleInfo(LCTYPE type) QByteArray buff(cnt, 0); - QT_WA({ - cnt = GetLocaleInfoW(id, type, - reinterpret_cast(buff.data()), - buff.size()/2); - } , { - cnt = GetLocaleInfoA(id, type, - buff.data(), buff.size()); - }); + cnt = GetLocaleInfo(id, type, reinterpret_cast(buff.data()), buff.size() / 2); if (cnt == 0) { qWarning("QLocale: empty windows locale info (%d)", (int)type); return QString(); } - QString result; - QT_WA({ - result = QString::fromUtf16(reinterpret_cast(buff.data())); - } , { - result = QString::fromLocal8Bit(buff.data()); - }); - return result; + return QString::fromWCharArray(reinterpret_cast(buff.data())); } QByteArray getWinLocaleName(LCID id = LOCALE_USER_DEFAULT) @@ -445,20 +425,19 @@ QByteArray getWinLocaleName(LCID id = LOCALE_USER_DEFAULT) } } - if (QSysInfo::WindowsVersion == QSysInfo::WV_95 - || (QSysInfo::WindowsVersion & QSysInfo::WV_CE_based)) { - result = winLangCodeToIsoName(id != LOCALE_USER_DEFAULT ? id : GetUserDefaultLCID()); - } else { - if (id == LOCALE_USER_DEFAULT) - id = GetUserDefaultLCID(); - QString resultuage = winIso639LangName(id); - QString country = winIso3116CtryName(id); - result = resultuage.toLatin1(); - if (!country.isEmpty()) { - result += '_'; - result += country.toLatin1(); - } +#if defined(Q_OS_WINCE) + result = winLangCodeToIsoName(id != LOCALE_USER_DEFAULT ? id : GetUserDefaultLCID()); +#else + if (id == LOCALE_USER_DEFAULT) + id = GetUserDefaultLCID(); + QString resultuage = winIso639LangName(id); + QString country = winIso3116CtryName(id); + result = resultuage.toLatin1(); + if (!country.isEmpty()) { + result += '_'; + result += country.toLatin1(); } +#endif return result; } @@ -544,15 +523,9 @@ static QString winDateToString(const QDate &date, DWORD flags) LCID id = GetUserDefaultLCID(); - QT_WA({ - TCHAR buf[255]; - if (GetDateFormatW(id, flags, &st, 0, buf, 255)) - return QString::fromUtf16((ushort*)buf); - } , { - char buf[255]; - if (GetDateFormatA(id, flags, &st, 0, (char*)&buf, 255)) - return QString::fromLocal8Bit(buf); - }); + wchar_t buf[255]; + if (GetDateFormat(id, flags, &st, 0, buf, 255)) + return QString::fromWCharArray(buf); return QString(); } @@ -569,15 +542,9 @@ static QString winTimeToString(const QTime &time) DWORD flags = 0; LCID id = GetUserDefaultLCID(); - QT_WA({ - TCHAR buf[255]; - if (GetTimeFormatW(id, flags, &st, 0, buf, 255)) - return QString::fromUtf16((ushort*)buf); - } , { - char buf[255]; - if (GetTimeFormatA(id, flags, &st, 0, (char*)&buf, 255)) - return QString::fromLocal8Bit(buf); - }); + wchar_t buf[255]; + if (GetTimeFormat(id, flags, &st, 0, buf, 255)) + return QString::fromWCharArray(buf); return QString(); } @@ -626,12 +593,10 @@ static QString winMonthName(int month, bool short_format) static QLocale::MeasurementSystem winSystemMeasurementSystem() { LCID id = GetUserDefaultLCID(); - TCHAR output[2]; + wchar_t output[2]; if (GetLocaleInfo(id, LOCALE_IMEASURE, output, 2)) { - QString iMeasure = QT_WA_INLINE( - QString::fromUtf16(reinterpret_cast(output)), - QString::fromLocal8Bit(reinterpret_cast(output))); + QString iMeasure = QString::fromWCharArray(output); if (iMeasure == QLatin1String("1")) { return QLocale::ImperialSystem; } @@ -643,12 +608,10 @@ static QLocale::MeasurementSystem winSystemMeasurementSystem() static QString winSystemAMText() { LCID id = GetUserDefaultLCID(); - TCHAR output[15]; // maximum length including terminating zero character for Win2003+ + wchar_t output[15]; // maximum length including terminating zero character for Win2003+ if (GetLocaleInfo(id, LOCALE_S1159, output, 15)) { - return QT_WA_INLINE( - QString::fromUtf16(reinterpret_cast(output)), - QString::fromLocal8Bit(reinterpret_cast(output))); + return QString::fromWCharArray(output); } return QString(); @@ -657,12 +620,10 @@ static QString winSystemAMText() static QString winSystemPMText() { LCID id = GetUserDefaultLCID(); - TCHAR output[15]; // maximum length including terminating zero character for Win2003+ + wchar_t output[15]; // maximum length including terminating zero character for Win2003+ if (GetLocaleInfo(id, LOCALE_S2359, output, 15)) { - return QT_WA_INLINE( - QString::fromUtf16(reinterpret_cast(output)), - QString::fromLocal8Bit(reinterpret_cast(output))); + return QString::fromWCharArray(output); } return QString(); @@ -766,9 +727,6 @@ QVariant QSystemLocale::query(QueryType type, QVariant in = QVariant()) const return QVariant(); } -/* Win95 doesn't have a function to return the ISO lang/country name of the user's locale. - Instead it can return a "Windows code". This maps windows codes to ISO country names. */ - struct WindowsToISOListElt { ushort windows_code; char iso_name[6]; @@ -924,15 +882,9 @@ static QString winIso639LangName(LCID id) // Windows returns the wrong ISO639 for some languages, we need to detect them here using // the language code QString lang_code; - QT_WA({ - TCHAR out[256]; - if (GetLocaleInfoW(id, LOCALE_ILANGUAGE, out, 255)) - lang_code = QString::fromUtf16((ushort*)out); - } , { - char out[256]; - if (GetLocaleInfoA(id, LOCALE_ILANGUAGE, out, 255)) - lang_code = QString::fromLocal8Bit(out); - }); + wchar_t out[256]; + if (GetLocaleInfo(id, LOCALE_ILANGUAGE, out, 255)) + lang_code = QString::fromWCharArray(out); if (!lang_code.isEmpty()) { const char *endptr; @@ -954,15 +906,8 @@ static QString winIso639LangName(LCID id) return result; // not one of the problematic languages - do the usual lookup - QT_WA({ - TCHAR out[256]; - if (GetLocaleInfoW(id, LOCALE_SISO639LANGNAME , out, 255)) - result = QString::fromUtf16((ushort*)out); - } , { - char out[256]; - if (GetLocaleInfoA(id, LOCALE_SISO639LANGNAME, out, 255)) - result = QString::fromLocal8Bit(out); - }); + if (GetLocaleInfo(id, LOCALE_SISO639LANGNAME , out, 255)) + result = QString::fromWCharArray(out); return result; } @@ -971,15 +916,9 @@ static QString winIso3116CtryName(LCID id) { QString result; - QT_WA({ - TCHAR out[256]; - if (GetLocaleInfoW(id, LOCALE_SISO3166CTRYNAME, out, 255)) - result = QString::fromUtf16((ushort*)out); - } , { - char out[256]; - if (GetLocaleInfoA(id, LOCALE_SISO3166CTRYNAME, out, 255)) - result = QString::fromLocal8Bit(out); - }); + wchar_t out[256]; + if (GetLocaleInfo(id, LOCALE_SISO3166CTRYNAME, out, 255)) + result = QString::fromWCharArray(out); return result; } @@ -2689,7 +2628,7 @@ static QString timeZone() DWORD res = GetTimeZoneInformation(&info); if (res == TIME_ZONE_ID_UNKNOWN) return QString(); - return QString::fromUtf16(reinterpret_cast (info.StandardName)); + return QString::fromWCharArray(info.StandardName); #elif defined(Q_OS_WIN) _tzset(); # if defined(_MSC_VER) && _MSC_VER >= 1400 diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 71482f5..b160b90 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -3714,13 +3714,13 @@ QByteArray qt_winQString2MB(const QChar *ch, int uclen) BOOL used_def; QByteArray mb(4096, 0); int len; - while (!(len=WideCharToMultiByte(CP_ACP, 0, (const WCHAR*)ch, uclen, + while (!(len=WideCharToMultiByte(CP_ACP, 0, (const wchar_t*)ch, uclen, mb.data(), mb.size()-1, 0, &used_def))) { int r = GetLastError(); if (r == ERROR_INSUFFICIENT_BUFFER) { mb.resize(1+WideCharToMultiByte(CP_ACP, 0, - (const WCHAR*)ch, uclen, + (const wchar_t*)ch, uclen, 0, 0, 0, &used_def)); // and try again... } else { @@ -3741,9 +3741,9 @@ QString qt_winMB2QString(const char *mb, int mblen) if (!mb || !mblen) return QString(); const int wclen_auto = 4096; - WCHAR wc_auto[wclen_auto]; + wchar_t wc_auto[wclen_auto]; int wclen = wclen_auto; - WCHAR *wc = wc_auto; + wchar_t *wc = wc_auto; int len; while (!(len=MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, mb, mblen, wc, wclen))) @@ -3756,7 +3756,7 @@ QString qt_winMB2QString(const char *mb, int mblen) } else { wclen = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, mb, mblen, 0, 0); - wc = new WCHAR[wclen]; + wc = new wchar_t[wclen]; // and try again... } } else { @@ -3799,11 +3799,6 @@ QString QString::fromLocal8Bit(const char *str, int size) return QString(); if (size == 0 || (!*str && size < 0)) return QLatin1String(""); -#if defined(Q_OS_WIN32) - if(QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) { - return qt_winMB2QString(str, size); - } -#endif #if !defined(QT_NO_TEXTCODEC) if (size < 0) size = qstrlen(str); @@ -4697,16 +4692,7 @@ int QString::localeAwareCompare_helper(const QChar *data1, int length1, return ucstrcmp(data1, length1, data2, length2); #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) - int res; - QT_WA({ - const TCHAR* s1 = (TCHAR*)data1; - const TCHAR* s2 = (TCHAR*)data2; - res = CompareStringW(GetUserDefaultLCID(), 0, s1, length1, s2, length2); - } , { - QByteArray s1 = toLocal8Bit_helper(data1, length1); - QByteArray s2 = toLocal8Bit_helper(data2, length2); - res = CompareStringA(GetUserDefaultLCID(), 0, s1.data(), s1.length(), s2.data(), s2.length()); - }); + int res = CompareString(GetUserDefaultLCID(), 0, (wchar_t*)data1, length1, (wchar_t*)data2, length2); switch (res) { case CSTR_LESS_THAN: -- cgit v0.12 From cfadf08a6c06ce319f6144e724f45e4923e72778 Mon Sep 17 00:00:00 2001 From: Marius Storm-Olsen Date: Wed, 1 Jul 2009 11:49:51 +0200 Subject: Handle application paths larger than MAX_PATH, and fix potential buffer overflow These days we can easily get very long paths, so we should support application paths as long as needed. There was also a potention exploit in that if the path was MAX_PATH or larger, the string would not be \0 terminated (see MSDN docs for GetModuleFileName), and thus cause problems in QString::fromWCharArray(). Merge-request: 604 Reviewed-by: Marius Storm-Olsen --- src/corelib/kernel/qcoreapplication.cpp | 9 ++----- src/corelib/kernel/qcoreapplication_win.cpp | 40 ++++++++++++++++++++++++++--- 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index f0a3fec..e2708c3 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -1741,13 +1741,8 @@ QString QCoreApplication::applicationFilePath() if (!d->cachedApplicationFilePath.isNull()) return d->cachedApplicationFilePath; -#if defined( Q_WS_WIN ) - wchar_t module_name[MAX_PATH]; - GetModuleFileName(0, module_name, MAX_PATH); - module_name[MAX_PATH] = 0; - QFileInfo filePath = QString::fromWCharArray(module_name); - - d->cachedApplicationFilePath = filePath.filePath(); +#if defined(Q_WS_WIN) + d->cachedApplicationFilePath = QFileInfo(qAppFileName()).filePath(); return d->cachedApplicationFilePath; #elif defined(Q_WS_MAC) QString qAppFileName_str = qAppFileName(); diff --git a/src/corelib/kernel/qcoreapplication_win.cpp b/src/corelib/kernel/qcoreapplication_win.cpp index 657abd1..a71f284 100644 --- a/src/corelib/kernel/qcoreapplication_win.cpp +++ b/src/corelib/kernel/qcoreapplication_win.cpp @@ -76,9 +76,43 @@ Q_CORE_EXPORT int qWinAppCmdShow() // get main window sho Q_CORE_EXPORT QString qAppFileName() // get application file name { - wchar_t buffer[MAX_PATH]; - GetModuleFileName(0, buffer, MAX_PATH); - return QString::fromWCharArray(buffer); + // We do MAX_PATH + 2 here, and request with MAX_PATH + 1, so we can handle all paths + // up to, and including MAX_PATH size perfectly fine with string termination, as well + // as easily detect if the file path is indeed larger than MAX_PATH, in which case we + // need to use the heap instead. This is a work-around, since contrary to what the + // MSDN documentation states, GetModuleFileName sometimes doesn't set the + // ERROR_INSUFFICIENT_BUFFER error number, and we thus cannot rely on this value if + // GetModuleFileName(0, buffer, MAX_PATH) == MAX_PATH. + // GetModuleFileName(0, buffer, MAX_PATH + 1) == MAX_PATH just means we hit the normal + // file path limit, and we handle it normally, if the result is MAX_PATH + 1, we use + // heap (even if the result _might_ be exactly MAX_PATH + 1, but that's ok). + wchar_t buffer[MAX_PATH + 2]; + DWORD v = GetModuleFileName(0, buffer, MAX_PATH + 1); + buffer[MAX_PATH + 1] = 0; + + if (v == 0) + return QString(); + else if (v <= MAX_PATH) + return QString::fromWCharArray(buffer); + + // MAX_PATH sized buffer wasn't large enough to contain the full path, use heap + wchar_t *b = 0; + int i = 1; + size_t size; + do { + ++i; + size = MAX_PATH * i; + b = reinterpret_cast(realloc(b, (size + 1) * sizeof(wchar_t))); + if (b) + v = GetModuleFileName(NULL, b, size); + } while (b && v == size); + + if (b) + *(b + size) = 0; + QString res = QString::fromWCharArray(b); + free(b); + + return res; } void set_winapp_name() -- cgit v0.12 From 55137901012db28857fe7638e63c78743e277c56 Mon Sep 17 00:00:00 2001 From: miniak Date: Wed, 1 Jul 2009 11:49:54 +0200 Subject: src/gui: Remove QT_WA and non-Unicode code paths, dropping Win9x and NT support Also - Make winPeekMessage() & winPostMessage() obsolete - FlashWindowEx, IsValidLanguageGroup functions no longer resolved dynamically (available on >= Windows 2000) - LoadIcon/LoadCursor -> LoadImage w/LR_SHARED for system icons/cursors - qsystemtrayicon_win: use Shell_NotifyIconGetRect if available (Windows 7) Merge-request: 604 Reviewed-by: Marius Storm-Olsen --- src/corelib/global/qt_windows.h | 21 +- src/corelib/kernel/qeventdispatcher_win.cpp | 2 +- src/gui/accessible/qaccessible_win.cpp | 32 +- src/gui/dialogs/qdialog.cpp | 3 +- src/gui/dialogs/qfiledialog_p.h | 3 +- src/gui/dialogs/qfiledialog_win.cpp | 456 +++++-------------- src/gui/dialogs/qfilesystemmodel.cpp | 20 +- src/gui/dialogs/qpagesetupdialog_win.cpp | 3 +- src/gui/dialogs/qprintdialog_win.cpp | 76 +--- src/gui/dialogs/qwizard.cpp | 14 +- src/gui/image/qpixmap_win.cpp | 12 +- src/gui/inputmethod/qwininputcontext_win.cpp | 116 ++--- src/gui/itemviews/qfileiconprovider.cpp | 12 +- src/gui/kernel/qapplication.cpp | 18 +- src/gui/kernel/qapplication_win.cpp | 409 +++++------------ src/gui/kernel/qclipboard_win.cpp | 10 +- src/gui/kernel/qcursor_win.cpp | 44 +- src/gui/kernel/qdesktopwidget_win.cpp | 121 ++--- src/gui/kernel/qdnd_win.cpp | 75 ++-- src/gui/kernel/qguifunctions_wince.cpp | 24 +- src/gui/kernel/qguifunctions_wince.h | 8 +- src/gui/kernel/qkeymapper_win.cpp | 120 +---- src/gui/kernel/qmime_win.cpp | 146 +++--- src/gui/kernel/qsound_win.cpp | 40 +- src/gui/kernel/qwhatsthis.cpp | 8 +- src/gui/kernel/qwidget.cpp | 8 +- src/gui/kernel/qwidget_win.cpp | 127 ++---- src/gui/kernel/qwidget_wince.cpp | 46 +- src/gui/painting/qpdf.cpp | 2 +- src/gui/painting/qprintengine_pdf.cpp | 2 +- src/gui/painting/qprintengine_win.cpp | 646 +++++++++------------------ src/gui/painting/qprintengine_win_p.h | 16 +- src/gui/painting/qprinterinfo_win.cpp | 98 ++-- src/gui/painting/qregion.cpp | 4 - src/gui/painting/qwindowsurface_raster.cpp | 24 +- src/gui/painting/qwindowsurface_raster_p.h | 13 +- src/gui/styles/qwindowsstyle.cpp | 115 ++--- src/gui/styles/qwindowsvistastyle.cpp | 4 +- src/gui/styles/qwindowsxpstyle.cpp | 9 +- src/gui/text/qfont_win.cpp | 8 +- src/gui/text/qfontdatabase_win.cpp | 259 +++-------- src/gui/text/qfontengine_win.cpp | 440 ++++-------------- src/gui/text/qfontengine_win_p.h | 18 +- src/gui/util/qdesktopservices_win.cpp | 28 +- src/gui/util/qsystemtrayicon_win.cpp | 323 ++++---------- src/gui/widgets/qeffects.cpp | 97 ++-- src/gui/widgets/qframe.cpp | 2 +- src/gui/widgets/qmdisubwindow.cpp | 35 +- src/gui/widgets/qsizegrip.cpp | 3 +- src/gui/widgets/qworkspace.cpp | 26 +- 50 files changed, 1227 insertions(+), 2919 deletions(-) diff --git a/src/corelib/global/qt_windows.h b/src/corelib/global/qt_windows.h index 5df57e5..27c06e5 100644 --- a/src/corelib/global/qt_windows.h +++ b/src/corelib/global/qt_windows.h @@ -60,7 +60,6 @@ #endif // already defined when compiled with WINVER >= 0x0500 -// and we only use them in Qt::WV_2000 and Qt::WV_98 #ifndef SPI_SETMENUANIMATION #define SPI_SETMENUANIMATION 0x1003 #endif @@ -113,4 +112,24 @@ #define ETO_PDY 0x2000 #endif +// already defined when compiled with WINVER >= 0x0600 +#ifndef SPI_GETFLATMENU +#define SPI_GETFLATMENU 0x1022 +#endif +#ifndef CS_DROPSHADOW +#define CS_DROPSHADOW 0x00020000 +#endif +#ifndef CLEARTYPE_QUALITY +#define CLEARTYPE_QUALITY 5 +#endif + +#ifdef Q_WS_WINCE +#ifndef LR_DEFAULTSIZE +#define LR_DEFAULTSIZE 0 +#endif +#ifndef LR_SHARED +#define LR_SHARED 0 +#endif +#endif // Q_WS_WINCE + #endif // QT_WINDOWS_H diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index 23e4fa9..33b66f5 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -495,7 +495,7 @@ LRESULT CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp) static HWND qt_create_internal_window(const QEventDispatcherWin32 *eventDispatcher) { // make sure that multiple Qt's can coexist in the same process - QString className = QLatin1Strign("QEventDispatcherWin32_Internal_Widget") + QString::number(quintptr(qt_internal_proc)); + QString className = QLatin1String("QEventDispatcherWin32_Internal_Widget") + QString::number(quintptr(qt_internal_proc)); WNDCLASS wc; wc.style = 0; diff --git a/src/gui/accessible/qaccessible_win.cpp b/src/gui/accessible/qaccessible_win.cpp index ccb2673..bfacb94 100644 --- a/src/gui/accessible/qaccessible_win.cpp +++ b/src/gui/accessible/qaccessible_win.cpp @@ -177,14 +177,14 @@ void QAccessible::updateAccessibility(QObject *o, int who, Event reason) return; } - QByteArray soundName; + QString soundName; switch (reason) { case PopupMenuStart: - soundName = "MenuPopup"; + soundName = QLatin1String("MenuPopup"); break; case MenuCommand: - soundName = "MenuCommand"; + soundName = QLatin1String("MenuCommand"); break; case Alert: @@ -194,13 +194,13 @@ void QAccessible::updateAccessibility(QObject *o, int who, Event reason) if (mb) { switch (mb->icon()) { case QMessageBox::Warning: - soundName = "SystemExclamation"; + soundName = QLatin1String("SystemExclamation"); break; case QMessageBox::Critical: - soundName = "SystemHand"; + soundName = QLatin1String("SystemHand"); break; case QMessageBox::Information: - soundName = "SystemAsterisk"; + soundName = QLatin1String("SystemAsterisk"); break; default: break; @@ -208,7 +208,7 @@ void QAccessible::updateAccessibility(QObject *o, int who, Event reason) } else #endif // QT_NO_MESSAGEBOX { - soundName = "SystemAsterisk"; + soundName = QLatin1String("SystemAsterisk"); } } @@ -219,20 +219,16 @@ void QAccessible::updateAccessibility(QObject *o, int who, Event reason) if (soundName.size()) { #ifndef QT_NO_SETTINGS - QSettings settings(QLatin1String("HKEY_CURRENT_USER\\AppEvents\\Schemes\\Apps\\.Default\\") + - QString::fromLatin1(soundName.constData()), QSettings::NativeFormat); + QSettings settings(QLatin1String("HKEY_CURRENT_USER\\AppEvents\\Schemes\\Apps\\.Default\\") + soundName, + QSettings::NativeFormat); QString file = settings.value(QLatin1String(".Current/.")).toString(); #else - QString file; + QString file; #endif - if (!file.isEmpty()) { - QT_WA({ - PlaySoundW(reinterpret_cast (QString::fromLatin1(soundName).utf16()), 0, SND_ALIAS | SND_ASYNC | SND_NODEFAULT | SND_NOWAIT ); - } , { - PlaySoundA(soundName.constData(), 0, SND_ALIAS | SND_ASYNC | SND_NODEFAULT | SND_NOWAIT ); - }); - } - } + if (!file.isEmpty()) { + PlaySound(reinterpret_cast(soundName.utf16()), 0, SND_ALIAS | SND_ASYNC | SND_NODEFAULT | SND_NOWAIT); + } + } if (!isActive()) return; diff --git a/src/gui/dialogs/qdialog.cpp b/src/gui/dialogs/qdialog.cpp index 0288cd9..bb6c6d6 100644 --- a/src/gui/dialogs/qdialog.cpp +++ b/src/gui/dialogs/qdialog.cpp @@ -762,8 +762,7 @@ void QDialog::setVisible(bool visible) #ifdef Q_WS_WIN if (d->mainDef && isActiveWindow()) { BOOL snapToDefault = false; - if ( QT_WA_INLINE( SystemParametersInfo(SPI_GETSNAPTODEFBUTTON, 0, &snapToDefault, 0) , - SystemParametersInfoA(SPI_GETSNAPTODEFBUTTON, 0, &snapToDefault, 0) )) { + if (SystemParametersInfo(SPI_GETSNAPTODEFBUTTON, 0, &snapToDefault, 0)) { if (snapToDefault) QCursor::setPos(d->mainDef->mapToGlobal(d->mainDef->rect().center())); } diff --git a/src/gui/dialogs/qfiledialog_p.h b/src/gui/dialogs/qfiledialog_p.h index 654b3bb..d798f9d 100644 --- a/src/gui/dialogs/qfiledialog_p.h +++ b/src/gui/dialogs/qfiledialog_p.h @@ -187,8 +187,7 @@ public: #ifndef Q_OS_WINCE DWORD maxLength; QString drive = path.left(3); - if (QT_WA_INLINE(::GetVolumeInformationW(reinterpret_cast(drive.utf16()), NULL, 0, NULL, &maxLength, NULL, NULL, 0), - ::GetVolumeInformationA(drive.toLocal8Bit().constData(), NULL, 0, NULL, &maxLength, NULL, NULL, 0)) == FALSE) + if (::GetVolumeInformation(reinterpret_cast(drive.utf16()), NULL, 0, NULL, &maxLength, NULL, NULL, 0) == FALSE) return -1; return maxLength; #else diff --git a/src/gui/dialogs/qfiledialog_win.cpp b/src/gui/dialogs/qfiledialog_win.cpp index 4cb31f5..6883bf9 100644 --- a/src/gui/dialogs/qfiledialog_win.cpp +++ b/src/gui/dialogs/qfiledialog_win.cpp @@ -70,8 +70,8 @@ typedef struct qt_priv_browseinfo { HWND hwndOwner; LPCITEMIDLIST pidlRoot; - LPTSTR pszDisplayName; - LPCTSTR lpszTitle; + LPWSTR pszDisplayName; + LPCWSTR lpszTitle; UINT ulFlags; BFFCALLBACK lpfn; LPARAM lParam; @@ -90,6 +90,9 @@ typedef LPITEMIDLIST (WINAPI *PtrSHBrowseForFolder)(BROWSEINFO*); static PtrSHBrowseForFolder ptrSHBrowseForFolder = 0; typedef BOOL (WINAPI *PtrSHGetPathFromIDList)(LPITEMIDLIST,LPWSTR); static PtrSHGetPathFromIDList ptrSHGetPathFromIDList = 0; +typedef HRESULT (WINAPI *PtrSHGetMalloc)(LPMALLOC *); +static PtrSHGetMalloc ptrSHGetMalloc = 0; + QT_BEGIN_NAMESPACE @@ -111,20 +114,20 @@ static void qt_win_resolve_libs() #endif triedResolve = true; - if (!(QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based)) { #if !defined(Q_WS_WINCE) - QLibrary lib(QLatin1String("shell32")); - ptrSHBrowseForFolder = (PtrSHBrowseForFolder) lib.resolve("SHBrowseForFolderW"); - ptrSHGetPathFromIDList = (PtrSHGetPathFromIDList) lib.resolve("SHGetPathFromIDListW"); + QLibrary lib(QLatin1String("shell32")); + ptrSHBrowseForFolder = (PtrSHBrowseForFolder) lib.resolve("SHBrowseForFolderW"); + ptrSHGetPathFromIDList = (PtrSHGetPathFromIDList) lib.resolve("SHGetPathFromIDListW"); + ptrSHGetMalloc = (PtrSHGetMalloc) lib.resolve("SHGetMalloc"); #else - // CE stores them in a different lib and does not use unicode version - HINSTANCE handle = LoadLibraryW(L"Ceshell"); - ptrSHBrowseForFolder = (PtrSHBrowseForFolder)GetProcAddress(handle, L"SHBrowseForFolder"); - ptrSHGetPathFromIDList = (PtrSHGetPathFromIDList)GetProcAddress(handle, L"SHGetPathFromIDList"); - if (ptrSHBrowseForFolder && ptrSHGetPathFromIDList) - qt_priv_ptr_valid = true; + // CE stores them in a different lib and does not use unicode version + HINSTANCE handle = LoadLibraryW(L"Ceshell"); + ptrSHBrowseForFolder = (PtrSHBrowseForFolder)GetProcAddress(handle, L"SHBrowseForFolder"); + ptrSHGetPathFromIDList = (PtrSHGetPathFromIDList)GetProcAddress(handle, L"SHGetPathFromIDList"); + ptrSHGetMalloc = (PtrSHGetMalloc)GetProcAddress(handle, L"SHGetMalloc"); + if (ptrSHBrowseForFolder && ptrSHGetPathFromIDList && ptrSHGetMalloc) + qt_priv_ptr_valid = true; #endif - } } } @@ -186,95 +189,15 @@ static QString qt_win_selected_filter(const QString &filter, DWORD idx) return qt_win_make_filters_list(filter).at((int)idx - 1); } -#ifndef Q_WS_WINCE -// Static vars for OFNA funcs: -static QByteArray aInitDir; -static QByteArray aInitSel; -static QByteArray aTitle; -static QByteArray aFilter; -// Use ANSI strings and API - -// If you change this, then make sure you change qt_win_make_OFN (below) too -static OPENFILENAMEA *qt_win_make_OFNA(QWidget *parent, - const QString &initialSelection, - const QString &initialDirectory, - const QString &title, - const QString &filters, - QFileDialog::FileMode mode, - QFileDialog::Options options) -{ - if (parent) - parent = parent->window(); - else - parent = QApplication::activeWindow(); - - aTitle = title.toLocal8Bit(); - aInitDir = QDir::toNativeSeparators(initialDirectory).toLocal8Bit(); - if (initialSelection.isEmpty()) { - aInitSel = ""; - } else { - aInitSel = QDir::toNativeSeparators(initialSelection).toLocal8Bit(); - aInitSel.replace('<', ""); - aInitSel.replace('>', ""); - aInitSel.replace('\"', ""); - aInitSel.replace('|', ""); - } - int maxLen = mode == QFileDialog::ExistingFiles ? maxMultiLen : maxNameLen; - aInitSel.resize(maxLen + 1); // make room for return value - aFilter = filters.toLocal8Bit(); - - OPENFILENAMEA* ofn = new OPENFILENAMEA; - memset(ofn, 0, sizeof(OPENFILENAMEA)); - -#if defined(Q_CC_BOR) && (WINVER >= 0x0500) && (_WIN32_WINNT >= 0x0500) - // according to the MSDN, this should also be necessary for MSVC, but - // OPENFILENAME_SIZE_VERSION_400A is in not Microsoft header, as it seems - if (QApplication::winVersion()==Qt::WV_NT || QApplication::winVersion()&Qt::WV_DOS_based) { - ofn->lStructSize = OPENFILENAME_SIZE_VERSION_400A; - } else { - ofn->lStructSize = sizeof(OPENFILENAMEA); - } -#else - ofn->lStructSize = sizeof(OPENFILENAMEA); -#endif - Q_ASSERT(!parent ||parent->testAttribute(Qt::WA_WState_Created)); - ofn->hwndOwner = parent ? parent->winId() : 0; - ofn->lpstrFilter = aFilter; - ofn->lpstrFile = aInitSel.data(); - ofn->nMaxFile = maxLen; - ofn->lpstrInitialDir = aInitDir.data(); - ofn->lpstrTitle = aTitle.data(); - ofn->Flags = (OFN_NOCHANGEDIR | OFN_HIDEREADONLY | OFN_EXPLORER); - - if (mode == QFileDialog::ExistingFile || - mode == QFileDialog::ExistingFiles) - ofn->Flags |= (OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST); - if (mode == QFileDialog::ExistingFiles) - ofn->Flags |= (OFN_ALLOWMULTISELECT); - if (!(options & QFileDialog::DontConfirmOverwrite)) - ofn->Flags |= OFN_OVERWRITEPROMPT; - - return ofn; -} - -static void qt_win_clean_up_OFNA(OPENFILENAMEA **ofn) -{ - delete *ofn; - *ofn = 0; -} -#endif - static QString tFilters, tTitle, tInitDir; -#ifdef UNICODE -// If you change this, then make sure you change qt_win_make_OFNA (above) too static OPENFILENAME* qt_win_make_OFN(QWidget *parent, const QString& initialSelection, const QString& initialDirectory, const QString& title, const QString& filters, QFileDialog::FileMode mode, - QFileDialog::Options options) + QFileDialog::Options options) { if (parent) parent = parent->window(); @@ -286,14 +209,14 @@ static OPENFILENAME* qt_win_make_OFN(QWidget *parent, tTitle = title; QString initSel = QDir::toNativeSeparators(initialSelection); if (!initSel.isEmpty()) { - initSel.remove(QLatin1Char('<')); - initSel.remove(QLatin1Char('>')); - initSel.remove(QLatin1Char('\"')); - initSel.remove(QLatin1Char('|')); + initSel.remove(QLatin1Char('<')); + initSel.remove(QLatin1Char('>')); + initSel.remove(QLatin1Char('\"')); + initSel.remove(QLatin1Char('|')); } int maxLen = mode == QFileDialog::ExistingFiles ? maxMultiLen : maxNameLen; - TCHAR *tInitSel = new TCHAR[maxLen+1]; + wchar_t *tInitSel = new wchar_t[maxLen + 1]; if (initSel.length() > 0 && initSel.length() <= maxLen) memcpy(tInitSel, initSel.utf16(), (initSel.length()+1)*sizeof(QChar)); else @@ -302,24 +225,14 @@ static OPENFILENAME* qt_win_make_OFN(QWidget *parent, OPENFILENAME* ofn = new OPENFILENAME; memset(ofn, 0, sizeof(OPENFILENAME)); -#if defined(Q_CC_BOR) && (WINVER >= 0x0500) && (_WIN32_WINNT >= 0x0500) - // according to the MSDN, this should also be necessary for MSVC, but - // OPENFILENAME_SIZE_VERSION_400 is in not Microsoft header, as it seems - if (QApplication::winVersion()==Qt::WV_NT || QApplication::winVersion()&Qt::WV_DOS_based) { - ofn->lStructSize= OPENFILENAME_SIZE_VERSION_400; - } else { - ofn->lStructSize = sizeof(OPENFILENAME); - } -#else ofn->lStructSize = sizeof(OPENFILENAME); -#endif Q_ASSERT(!parent ||parent->testAttribute(Qt::WA_WState_Created)); ofn->hwndOwner = parent ? parent->winId() : 0; - ofn->lpstrFilter = (TCHAR *)tFilters.utf16(); + ofn->lpstrFilter = (wchar_t*)tFilters.utf16(); ofn->lpstrFile = tInitSel; ofn->nMaxFile = maxLen; - ofn->lpstrInitialDir = (TCHAR *)tInitDir.utf16(); - ofn->lpstrTitle = (TCHAR *)tTitle.utf16(); + ofn->lpstrInitialDir = (wchar_t*)tInitDir.utf16(); + ofn->lpstrTitle = (wchar_t*)tTitle.utf16(); ofn->Flags = (OFN_NOCHANGEDIR | OFN_HIDEREADONLY | OFN_EXPLORER); if (mode == QFileDialog::ExistingFile || mode == QFileDialog::ExistingFiles) @@ -332,7 +245,6 @@ static OPENFILENAME* qt_win_make_OFN(QWidget *parent, return ofn; } - static void qt_win_clean_up_OFN(OPENFILENAME **ofn) { delete [] (*ofn)->lpstrFile; @@ -340,8 +252,6 @@ static void qt_win_clean_up_OFN(OPENFILENAME **ofn) *ofn = 0; } -#endif // UNICODE - extern void qt_win_eatMouseMove(); QString qt_win_get_open_file_name(const QFileDialogArgs &args, @@ -377,35 +287,20 @@ QString qt_win_get_open_file_name(const QFileDialogArgs &args, modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true); modal_widget.setParent(args.parent, Qt::Window); QApplicationPrivate::enterModal(&modal_widget); - QT_WA({ - // Use Unicode strings and API - OPENFILENAME* ofn = qt_win_make_OFN(args.parent, args.selection, - args.directory, args.caption, - qt_win_filter(args.filter), - QFileDialog::ExistingFile, - args.options); - if (idx) - ofn->nFilterIndex = idx + 1; - if (GetOpenFileName(ofn)) { - result = QString::fromUtf16((ushort*)ofn->lpstrFile); - selFilIdx = ofn->nFilterIndex; - } - qt_win_clean_up_OFN(&ofn); - } , { - // Use ANSI strings and API - OPENFILENAMEA* ofn = qt_win_make_OFNA(args.parent, args.selection, - args.directory, args.caption, - qt_win_filter(args.filter), - QFileDialog::ExistingFile, - args.options); - if (idx) - ofn->nFilterIndex = idx + 1; - if (GetOpenFileNameA(ofn)) { - result = QString::fromLocal8Bit(ofn->lpstrFile); - selFilIdx = ofn->nFilterIndex; - } - qt_win_clean_up_OFNA(&ofn); - }); + + OPENFILENAME* ofn = qt_win_make_OFN(args.parent, args.selection, + args.directory, args.caption, + qt_win_filter(args.filter), + QFileDialog::ExistingFile, + args.options); + if (idx) + ofn->nFilterIndex = idx + 1; + if (GetOpenFileName(ofn)) { + result = QString::fromWCharArray(ofn->lpstrFile); + selFilIdx = ofn->nFilterIndex; + } + qt_win_clean_up_OFN(&ofn); + QApplicationPrivate::leaveModal(&modal_widget); qt_win_eatMouseMove(); @@ -422,7 +317,7 @@ QString qt_win_get_open_file_name(const QFileDialogArgs &args, QString qt_win_get_save_file_name(const QFileDialogArgs &args, QString *initialDirectory, - QString *selectedFilter) + QString *selectedFilter) { QString result; @@ -470,41 +365,22 @@ QString qt_win_get_save_file_name(const QFileDialogArgs &args, } } - QT_WA({ - // Use Unicode strings and API - OPENFILENAME *ofn = qt_win_make_OFN(args.parent, args.selection, - args.directory, args.caption, - qt_win_filter(args.filter), - QFileDialog::AnyFile, - args.options); - - ofn->lpstrDefExt = (TCHAR *)defaultSaveExt.utf16(); - - if (idx) - ofn->nFilterIndex = idx + 1; - if (GetSaveFileName(ofn)) { - result = QString::fromUtf16((ushort*)ofn->lpstrFile); - selFilIdx = ofn->nFilterIndex; - } - qt_win_clean_up_OFN(&ofn); - } , { - // Use ANSI strings and API - OPENFILENAMEA *ofn = qt_win_make_OFNA(args.parent, args.selection, - args.directory, args.caption, - qt_win_filter(args.filter), - QFileDialog::AnyFile, - args.options); - QByteArray asciiExt = defaultSaveExt.toAscii(); - ofn->lpstrDefExt = asciiExt.data(); - - if (idx) - ofn->nFilterIndex = idx + 1; - if (GetSaveFileNameA(ofn)) { - result = QString::fromLocal8Bit(ofn->lpstrFile); - selFilIdx = ofn->nFilterIndex; - } - qt_win_clean_up_OFNA(&ofn); - }); + OPENFILENAME *ofn = qt_win_make_OFN(args.parent, args.selection, + args.directory, args.caption, + qt_win_filter(args.filter), + QFileDialog::AnyFile, + args.options); + + ofn->lpstrDefExt = (wchar_t*)defaultSaveExt.utf16(); + + if (idx) + ofn->nFilterIndex = idx + 1; + if (GetSaveFileName(ofn)) { + result = QString::fromWCharArray(ofn->lpstrFile); + selFilIdx = ofn->nFilterIndex; + } + qt_win_clean_up_OFN(&ofn); + #if defined(Q_WS_WINCE) int semIndex = result.indexOf(QLatin1Char(';')); if (semIndex >= 0) @@ -558,73 +434,40 @@ QStringList qt_win_get_open_file_names(const QFileDialogArgs &args, modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true); modal_widget.setParent(args.parent, Qt::Window); QApplicationPrivate::enterModal(&modal_widget); - QT_WA({ - OPENFILENAME* ofn = qt_win_make_OFN(args.parent, args.selection, - args.directory, args.caption, - qt_win_filter(args.filter), - QFileDialog::ExistingFiles, - args.options); - if (idx) - ofn->nFilterIndex = idx + 1; - if (GetOpenFileName(ofn)) { - QString fileOrDir = QString::fromUtf16((ushort*)ofn->lpstrFile); - selFilIdx = ofn->nFilterIndex; - int offset = fileOrDir.length() + 1; - if (ofn->lpstrFile[offset] == 0) { - // Only one file selected; has full path - fi.setFile(fileOrDir); - QString res = fi.absoluteFilePath(); - if (!res.isEmpty()) - result.append(res); - } - else { - // Several files selected; first string is path - dir.setPath(fileOrDir); - QString f; - while(!(f = QString::fromUtf16((ushort*)ofn->lpstrFile+offset)).isEmpty()) { - fi.setFile(dir, f); - QString res = fi.absoluteFilePath(); - if (!res.isEmpty()) - result.append(res); - offset += f.length() + 1; - } - } + + OPENFILENAME* ofn = qt_win_make_OFN(args.parent, args.selection, + args.directory, args.caption, + qt_win_filter(args.filter), + QFileDialog::ExistingFiles, + args.options); + if (idx) + ofn->nFilterIndex = idx + 1; + if (GetOpenFileName(ofn)) { + QString fileOrDir = QString::fromWCharArray(ofn->lpstrFile); + selFilIdx = ofn->nFilterIndex; + int offset = fileOrDir.length() + 1; + if (ofn->lpstrFile[offset] == 0) { + // Only one file selected; has full path + fi.setFile(fileOrDir); + QString res = fi.absoluteFilePath(); + if (!res.isEmpty()) + result.append(res); } - qt_win_clean_up_OFN(&ofn); - } , { - OPENFILENAMEA* ofn = qt_win_make_OFNA(args.parent, args.selection, - args.directory, args.caption, - qt_win_filter(args.filter), - QFileDialog::ExistingFiles, - args.options); - if (idx) - ofn->nFilterIndex = idx + 1; - if (GetOpenFileNameA(ofn)) { - QByteArray fileOrDir(ofn->lpstrFile); - selFilIdx = ofn->nFilterIndex; - int offset = fileOrDir.length() + 1; - if (ofn->lpstrFile[offset] == '\0') { - // Only one file selected; has full path - fi.setFile(QString::fromLocal8Bit(fileOrDir)); + else { + // Several files selected; first string is path + dir.setPath(fileOrDir); + QString f; + while(!(f = QString::fromWCharArray(ofn->lpstrFile + offset)).isEmpty()) { + fi.setFile(dir, f); QString res = fi.absoluteFilePath(); if (!res.isEmpty()) result.append(res); + offset += f.length() + 1; } - else { - // Several files selected; first string is path - dir.setPath(QString::fromLocal8Bit(fileOrDir)); - QByteArray f; - while (!(f = QByteArray(ofn->lpstrFile + offset)).isEmpty()) { - fi.setFile(dir, QString::fromLocal8Bit(f)); - QString res = fi.absoluteFilePath(); - if (!res.isEmpty()) - result.append(res); - offset += f.length() + 1; - } - } - qt_win_clean_up_OFNA(&ofn); } - }); + } + qt_win_clean_up_OFN(&ofn); + QApplicationPrivate::leaveModal(&modal_widget); qt_win_eatMouseMove(); @@ -647,34 +490,20 @@ static int __stdcall winGetExistDirCallbackProc(HWND hwnd, if (uMsg == BFFM_INITIALIZED && lpData != 0) { QString *initDir = (QString *)(lpData); if (!initDir->isEmpty()) { - // ### Lars asks: is this correct for the A version???? - QT_WA({ - SendMessage(hwnd, BFFM_SETSELECTION, TRUE, LPARAM(initDir->utf16())); - } , { - SendMessageA(hwnd, BFFM_SETSELECTION, TRUE, LPARAM(initDir->utf16())); - }); + SendMessage(hwnd, BFFM_SETSELECTION, TRUE, LPARAM(initDir->utf16())); } } else if (uMsg == BFFM_SELCHANGED) { - QT_WA({ - qt_win_resolve_libs(); - TCHAR path[MAX_PATH]; + qt_win_resolve_libs(); + if (ptrSHGetPathFromIDList) { + wchar_t path[MAX_PATH]; ptrSHGetPathFromIDList(LPITEMIDLIST(lParam), path); - QString tmpStr = QString::fromUtf16((ushort*)path); + QString tmpStr = QString::fromWCharArray(path); if (!tmpStr.isEmpty()) SendMessage(hwnd, BFFM_ENABLEOK, 1, 1); else SendMessage(hwnd, BFFM_ENABLEOK, 0, 0); SendMessage(hwnd, BFFM_SETSTATUSTEXT, 1, LPARAM(path)); - } , { - char path[MAX_PATH]; - SHGetPathFromIDListA(LPITEMIDLIST(lParam), path); - QString tmpStr = QString::fromLocal8Bit(path); - if (!tmpStr.isEmpty()) - SendMessageA(hwnd, BFFM_ENABLEOK, 1, 1); - else - SendMessageA(hwnd, BFFM_ENABLEOK, 0, 0); - SendMessageA(hwnd, BFFM_SETSTATUSTEXT, 1, LPARAM(path)); - }); + } } return 0; } @@ -700,116 +529,49 @@ QString qt_win_get_existing_directory(const QFileDialogArgs &args) modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true); modal_widget.setParent(parent, Qt::Window); QApplicationPrivate::enterModal(&modal_widget); -#if !defined(Q_WS_WINCE) - QT_WA({ - qt_win_resolve_libs(); - QString initDir = QDir::toNativeSeparators(args.directory); - TCHAR path[MAX_PATH]; - TCHAR initPath[MAX_PATH]; - initPath[0] = 0; - path[0] = 0; - tTitle = args.caption; - BROWSEINFO bi; - Q_ASSERT(!parent ||parent->testAttribute(Qt::WA_WState_Created)); - bi.hwndOwner = (parent ? parent->winId() : 0); - bi.pidlRoot = NULL; - //### This does not seem to be respected? - the dialog always displays "Browse for folder" - bi.lpszTitle = (TCHAR*)tTitle.utf16(); - bi.pszDisplayName = initPath; - bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT | BIF_NEWDIALOGSTYLE; - bi.lpfn = winGetExistDirCallbackProc; - bi.lParam = LPARAM(&initDir); - if (ptrSHBrowseForFolder) { - LPITEMIDLIST pItemIDList = ptrSHBrowseForFolder(&bi); - if (pItemIDList && ptrSHGetPathFromIDList) { - ptrSHGetPathFromIDList(pItemIDList, path); - IMalloc *pMalloc; - if (SHGetMalloc(&pMalloc) != NOERROR) - result = QString(); - else { - pMalloc->Free(pItemIDList); - pMalloc->Release(); - result = QString::fromUtf16((ushort*)path); - } - } else - result = QString(); - } - tTitle = QString(); - } , { - QString initDir = QDir::toNativeSeparators(args.directory); - char path[MAX_PATH]; - char initPath[MAX_PATH]; - QByteArray ctitle = args.caption.toLocal8Bit(); - initPath[0]=0; - path[0]=0; - BROWSEINFOA bi; - Q_ASSERT(!parent ||parent->testAttribute(Qt::WA_WState_Created)); - bi.hwndOwner = (parent ? parent->winId() : 0); - bi.pidlRoot = NULL; - bi.lpszTitle = ctitle; - bi.pszDisplayName = initPath; - bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT | BIF_NEWDIALOGSTYLE; - bi.lpfn = winGetExistDirCallbackProc; - bi.lParam = LPARAM(&initDir); - LPITEMIDLIST pItemIDList = SHBrowseForFolderA(&bi); - if (pItemIDList) { - SHGetPathFromIDListA(pItemIDList, path); - IMalloc *pMalloc; - if (SHGetMalloc(&pMalloc) != NOERROR) - result = QString(); - else { - pMalloc->Free(pItemIDList); - pMalloc->Release(); - result = QString::fromLocal8Bit(path); - } - } else - result = QString(); - }); -#else - qt_win_resolve_libs(); + QString initDir = QDir::toNativeSeparators(args.directory); - TCHAR path[MAX_PATH]; - TCHAR initPath[MAX_PATH]; - memset(initPath, 0 , MAX_PATH*sizeof(TCHAR)); - memset(path, 0, MAX_PATH*sizeof(TCHAR)); + wchar_t path[MAX_PATH]; + wchar_t initPath[MAX_PATH]; + initPath[0] = 0; + path[0] = 0; tTitle = args.caption; + +#if !defined(Q_WS_WINCE) + BROWSEINFO bi; +#else qt_BROWSEINFO bi; +#endif + Q_ASSERT(!parent ||parent->testAttribute(Qt::WA_WState_Created)); bi.hwndOwner = (parent ? parent->winId() : 0); bi.pidlRoot = NULL; - bi.lpszTitle = (TCHAR*)tTitle.utf16(); + //### This does not seem to be respected? - the dialog always displays "Browse for folder" + bi.lpszTitle = (wchar_t*)tTitle.utf16(); bi.pszDisplayName = initPath; bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT | BIF_NEWDIALOGSTYLE; bi.lpfn = winGetExistDirCallbackProc; bi.lParam = LPARAM(&initDir); + + qt_win_resolve_libs(); if (ptrSHBrowseForFolder) { LPITEMIDLIST pItemIDList = ptrSHBrowseForFolder((BROWSEINFO*)&bi); - if (pItemIDList && ptrSHGetPathFromIDList) { + if (pItemIDList) { ptrSHGetPathFromIDList(pItemIDList, path); IMalloc *pMalloc; - if (SHGetMalloc(&pMalloc) != NOERROR) - result = QString(); - else { + if (ptrSHGetMalloc(&pMalloc) == NOERROR) { pMalloc->Free(pItemIDList); pMalloc->Release(); - result = QString::fromUtf16((ushort*)path); + result = QString::fromWCharArray(path); } - } else - result = QString(); + } } tTitle = QString(); -#endif QApplicationPrivate::leaveModal(&modal_widget); qt_win_eatMouseMove(); - // Due to a bug on Windows Me, we need to reset the current - // directory - if ((QSysInfo::WindowsVersion == QSysInfo::WV_98 || QSysInfo::WindowsVersion == QSysInfo::WV_Me) - && QDir::currentPath() != currentDir) - QDir::setCurrent(currentDir); - if (!result.isEmpty()) result.replace(QLatin1Char('\\'), QLatin1Char('/')); return result; diff --git a/src/gui/dialogs/qfilesystemmodel.cpp b/src/gui/dialogs/qfilesystemmodel.cpp index 347a084..e523ec3 100644 --- a/src/gui/dialogs/qfilesystemmodel.cpp +++ b/src/gui/dialogs/qfilesystemmodel.cpp @@ -296,22 +296,14 @@ static QString qt_GetLongPathName(const QString &strShortPath) #else QString longSection = QDir::toNativeSeparators(section); #endif - QT_WA({ - WIN32_FIND_DATAW findData; - h = ::FindFirstFileW((wchar_t *)longSection.utf16(), &findData); - if (h != INVALID_HANDLE_VALUE) - longPath.append(QString::fromUtf16((ushort*)findData.cFileName)); - } , { - WIN32_FIND_DATAA findData; - h = ::FindFirstFileA(section.toLocal8Bit(), &findData); - if (h != INVALID_HANDLE_VALUE) - longPath.append(QString::fromLocal8Bit(findData.cFileName)); - }); - if (h == INVALID_HANDLE_VALUE) { + WIN32_FIND_DATA findData; + h = ::FindFirstFile((wchar_t*)longSection.utf16(), &findData); + if (h != INVALID_HANDLE_VALUE) { + longPath.append(QString::fromWCharArray(findData.cFileName)); + ::FindClose(h); + } else { longPath.append(section); break; - } else { - ::FindClose(h); } } if (it != constEnd) diff --git a/src/gui/dialogs/qpagesetupdialog_win.cpp b/src/gui/dialogs/qpagesetupdialog_win.cpp index 136f939..a84a7ce 100644 --- a/src/gui/dialogs/qpagesetupdialog_win.cpp +++ b/src/gui/dialogs/qpagesetupdialog_win.cpp @@ -81,8 +81,7 @@ int QPageSetupDialog::exec() HGLOBAL hDevMode; int devModeSize; if (!ep->globalDevMode) { - QT_WA( { devModeSize = sizeof(DEVMODEW) + ((DEVMODEW *) ep->devMode)->dmDriverExtra; }, - { devModeSize = sizeof(DEVMODEA) + ((DEVMODEA *) ep->devMode)->dmDriverExtra; }); + devModeSize = sizeof(DEVMODE) + ep->devMode->dmDriverExtra; hDevMode = GlobalAlloc(GHND, devModeSize); if (hDevMode) { void *dest = GlobalLock(hDevMode); diff --git a/src/gui/dialogs/qprintdialog_win.cpp b/src/gui/dialogs/qprintdialog_win.cpp index e89ce90..6022a66 100644 --- a/src/gui/dialogs/qprintdialog_win.cpp +++ b/src/gui/dialogs/qprintdialog_win.cpp @@ -77,27 +77,22 @@ public: QWin32PrintEnginePrivate *ep; }; -#ifndef Q_OS_WINCE -// If you change this function, make sure you also change the unicode equivalent -template -static PrintDialog *qt_win_make_PRINTDLG(QWidget *parent, - QPrintDialog *pdlg, - QPrintDialogPrivate *d, HGLOBAL *tempDevNames) +static PRINTDLG* qt_win_make_PRINTDLG(QWidget *parent, + QPrintDialog *pdlg, + QPrintDialogPrivate *d, HGLOBAL *tempDevNames) { - PrintDialog *pd = new PrintDialog; - memset(pd, 0, sizeof(PrintDialog)); - pd->lStructSize = sizeof(PrintDialog); + PRINTDLG *pd = new PRINTDLG; + memset(pd, 0, sizeof(PRINTDLG)); + pd->lStructSize = sizeof(PRINTDLG); - void *devMode = sizeof(DeviceMode) == sizeof(DEVMODEA) - ? (void *) d->ep->devModeA() - : (void *) d->ep->devModeW(); + DEVMODE *devMode = d->ep->devMode; if (devMode) { - int size = sizeof(DeviceMode) + ((DeviceMode *) devMode)->dmDriverExtra; + int size = sizeof(DEVMODE) + devMode->dmDriverExtra; pd->hDevMode = GlobalAlloc(GHND, size); { void *dest = GlobalLock(pd->hDevMode); - memcpy(dest, d->ep->devMode, size); + memcpy(dest, devMode, size); GlobalUnlock(pd->hDevMode); } } else { @@ -140,20 +135,14 @@ static PrintDialog *qt_win_make_PRINTDLG(QWidget *parent, return pd; } -#endif // Q_OS_WINCE -// If you change this function, make sure you also change the ansi equivalent -template -static void qt_win_clean_up_PRINTDLG(T **pd) +static void qt_win_clean_up_PRINTDLG(PRINTDLG **pd) { delete *pd; *pd = 0; } - -// If you change this function, make sure you also change the ansi equivalent -template -static void qt_win_read_back_PRINTDLG(T *pd, QPrintDialog *pdlg, QPrintDialogPrivate *d) +static void qt_win_read_back_PRINTDLG(PRINTDLG *pd, QPrintDialog *pdlg, QPrintDialogPrivate *d) { if (pd->Flags & PD_SELECTION) { pdlg->setPrintRange(QPrintDialog::Selection); @@ -236,32 +225,18 @@ int QPrintDialogPrivate::openWindowsPrintDialogModally() bool result; bool done; - void *pd = QT_WA_INLINE( - (void*)(qt_win_make_PRINTDLG(parent, q, this, tempDevNames)), - (void*)(qt_win_make_PRINTDLG(parent, q, this, tempDevNames)) - ); + PRINTDLG *pd = qt_win_make_PRINTDLG(parent, q, this, tempDevNames); do { done = true; - QT_WA({ - PRINTDLGW *pdw = reinterpret_cast(pd); - result = PrintDlgW(pdw); - if ((pdw->Flags & PD_PAGENUMS) && (pdw->nFromPage > pdw->nToPage)) - done = false; - if (result && pdw->hDC == 0) - result = false; - else if (!result) - done = true; - }, { - PRINTDLGA *pda = reinterpret_cast(pd); - result = PrintDlgA(pda); - if ((pda->Flags & PD_PAGENUMS) && (pda->nFromPage > pda->nToPage)) - done = false; - if (result && pda->hDC == 0) - result = false; - else if (!result) - done = true; - }); + result = PrintDlg(pd); + if ((pd->Flags & PD_PAGENUMS) && (pd->nFromPage > pd->nToPage)) + done = false; + if (result && pd->hDC == 0) + result = false; + else if (!result) + done = true; + if (!done) { QMessageBox::warning(0, QPrintDialog::tr("Print"), QPrintDialog::tr("The 'From' value cannot be greater than the 'To' value."), @@ -275,15 +250,8 @@ int QPrintDialogPrivate::openWindowsPrintDialogModally() // write values back... if (result) { - QT_WA({ - PRINTDLGW *pdw = reinterpret_cast(pd); - qt_win_read_back_PRINTDLG(pdw, q, this); - qt_win_clean_up_PRINTDLG(&pdw); - }, { - PRINTDLGA *pda = reinterpret_cast(pd); - qt_win_read_back_PRINTDLG(pda, q, this); - qt_win_clean_up_PRINTDLG(&pda); - }); + qt_win_read_back_PRINTDLG(pd, q, this); + qt_win_clean_up_PRINTDLG(&pd); // update printer validity printer->d_func()->validPrinter = !ep->name.isEmpty(); } diff --git a/src/gui/dialogs/qwizard.cpp b/src/gui/dialogs/qwizard.cpp index 3fdea54..a7dccd8 100644 --- a/src/gui/dialogs/qwizard.cpp +++ b/src/gui/dialogs/qwizard.cpp @@ -1251,13 +1251,7 @@ void QWizardPrivate::updateMinMaxSizes(const QWizardLayoutInfo &info) extraHeight = vistaHelper->titleBarSize() + vistaHelper->topOffset(); #endif QSize minimumSize = mainLayout->totalMinimumSize() + QSize(0, extraHeight); - QSize maximumSize; - bool skipMaxSize = false; -#if defined(Q_WS_WIN) - if (QSysInfo::WindowsVersion <= QSysInfo::WV_Me) // ### See Tasks 164078 and 161660 - skipMaxSize = true; -#endif - maximumSize = mainLayout->totalMaximumSize(); + QSize maximumSize = mainLayout->totalMaximumSize(); if (info.header && headerWidget->maximumWidth() != QWIDGETSIZE_MAX) { minimumSize.setWidth(headerWidget->maximumWidth()); maximumSize.setWidth(headerWidget->maximumWidth()); @@ -1276,13 +1270,11 @@ void QWizardPrivate::updateMinMaxSizes(const QWizardLayoutInfo &info) } if (q->maximumWidth() == maximumWidth) { maximumWidth = maximumSize.width(); - if (!skipMaxSize) - q->setMaximumWidth(maximumWidth); + q->setMaximumWidth(maximumWidth); } if (q->maximumHeight() == maximumHeight) { maximumHeight = maximumSize.height(); - if (!skipMaxSize) - q->setMaximumHeight(maximumHeight); + q->setMaximumHeight(maximumHeight); } } diff --git a/src/gui/image/qpixmap_win.cpp b/src/gui/image/qpixmap_win.cpp index 2c84ce7..56b53bd 100644 --- a/src/gui/image/qpixmap_win.cpp +++ b/src/gui/image/qpixmap_win.cpp @@ -179,13 +179,7 @@ QPixmap QPixmap::fromWinHBITMAP(HBITMAP bitmap, HBitmapFormat format) BITMAP bitmap_info; memset(&bitmap_info, 0, sizeof(BITMAP)); - int res; - QT_WA({ - res = GetObjectW(bitmap, sizeof(BITMAP), &bitmap_info); - } , { - res = GetObjectA(bitmap, sizeof(BITMAP), &bitmap_info); - }); - + int res = GetObject(bitmap, sizeof(BITMAP), &bitmap_info); if (!res) { qErrnoWarning("QPixmap::fromWinHBITMAP(), failed to get bitmap info"); return QPixmap(); @@ -417,9 +411,9 @@ QPixmap convertHIconToPixmap( const HICON icon, bool large) QPixmap loadIconFromShell32( int resourceId, int size ) { #ifdef Q_OS_WINCE - HMODULE hmod = LoadLibrary((const wchar_t *) QString::fromLatin1("ceshell.dll").utf16()); + HMODULE hmod = LoadLibrary(L"ceshell.dll"); #else - HMODULE hmod = LoadLibraryA("shell32.dll"); + HMODULE hmod = LoadLibrary(L"shell32.dll"); #endif if( hmod ) { HICON iconHandle = (HICON)LoadImage(hmod, MAKEINTRESOURCE(resourceId), IMAGE_ICON, size, size, 0); diff --git a/src/gui/inputmethod/qwininputcontext_win.cpp b/src/gui/inputmethod/qwininputcontext_win.cpp index 3bbde89..741d8da 100644 --- a/src/gui/inputmethod/qwininputcontext_win.cpp +++ b/src/gui/inputmethod/qwininputcontext_win.cpp @@ -45,16 +45,11 @@ #include "qfont.h" #include "qwidget.h" #include "qapplication.h" -#include "qlibrary.h" #include "qevent.h" #include "qtextformat.h" //#define Q_IME_DEBUG -/* Active Input method support on Win95/98/NT */ -#include -#include - #ifdef Q_IME_DEBUG #include "qdebug.h" #endif @@ -218,25 +213,6 @@ static DWORD WM_MSIME_MOUSE = 0; QWinInputContext::QWinInputContext(QObject *parent) : QInputContext(parent), recursionGuard(false) { - if (QSysInfo::WindowsVersion < QSysInfo::WV_2000) { - // try to get the Active IMM COM object on Win95/98/NT, where english versions don't - // support the regular Windows input methods. - if (CoCreateInstance(CLSID_CActiveIMM, NULL, CLSCTX_INPROC_SERVER, - IID_IActiveIMMApp, (LPVOID *)&aimm) != S_OK) { - aimm = 0; - } - if (aimm && (aimm->QueryInterface(IID_IActiveIMMMessagePumpOwner, (LPVOID *)&aimmpump) != S_OK || - aimm->Activate(true) != S_OK)) { - aimm->Release(); - aimm = 0; - if (aimmpump) - aimmpump->Release(); - aimmpump = 0; - } - if (aimmpump) - aimmpump->Start(); - } - #ifndef Q_WS_WINCE QSysInfo::WinVersion ver = QSysInfo::windowsVersion(); if (ver & QSysInfo::WV_NT_based && ver >= QSysInfo::WV_VISTA) { @@ -262,25 +238,21 @@ QWinInputContext::QWinInputContext(QObject *parent) delete []lpList; } } else { - // figure out whether a RTL language is installed - typedef BOOL(WINAPI *PtrIsValidLanguageGroup)(DWORD,DWORD); - PtrIsValidLanguageGroup isValidLanguageGroup = (PtrIsValidLanguageGroup)QLibrary::resolve(QLatin1String("kernel32"), "IsValidLanguageGroup"); - if (isValidLanguageGroup) { - qt_use_rtl_extensions = isValidLanguageGroup(LGRPID_ARABIC, LGRPID_INSTALLED) - || isValidLanguageGroup(LGRPID_HEBREW, LGRPID_INSTALLED); - } - qt_use_rtl_extensions |= IsValidLocale(MAKELCID(MAKELANGID(LANG_ARABIC, SUBLANG_DEFAULT), SORT_DEFAULT), LCID_INSTALLED) - || IsValidLocale(MAKELCID(MAKELANGID(LANG_HEBREW, SUBLANG_DEFAULT), SORT_DEFAULT), LCID_INSTALLED) + // figure out whether a RTL language is installed + qt_use_rtl_extensions = IsValidLanguageGroup(LGRPID_ARABIC, LGRPID_INSTALLED) + || IsValidLanguageGroup(LGRPID_HEBREW, LGRPID_INSTALLED) + || IsValidLocale(MAKELCID(MAKELANGID(LANG_ARABIC, SUBLANG_DEFAULT), SORT_DEFAULT), LCID_INSTALLED) + || IsValidLocale(MAKELCID(MAKELANGID(LANG_HEBREW, SUBLANG_DEFAULT), SORT_DEFAULT), LCID_INSTALLED) #ifdef LANG_SYRIAC - || IsValidLocale(MAKELCID(MAKELANGID(LANG_SYRIAC, SUBLANG_DEFAULT), SORT_DEFAULT), LCID_INSTALLED) + || IsValidLocale(MAKELCID(MAKELANGID(LANG_SYRIAC, SUBLANG_DEFAULT), SORT_DEFAULT), LCID_INSTALLED) #endif - || IsValidLocale(MAKELCID(MAKELANGID(LANG_FARSI, SUBLANG_DEFAULT), SORT_DEFAULT), LCID_INSTALLED); + || IsValidLocale(MAKELCID(MAKELANGID(LANG_FARSI, SUBLANG_DEFAULT), SORT_DEFAULT), LCID_INSTALLED); } #else qt_use_rtl_extensions = false; #endif - WM_MSIME_MOUSE = QT_WA_INLINE(RegisterWindowMessage(L"MSIMEMouseOperation"), RegisterWindowMessageA("MSIMEMouseOperation")); + WM_MSIME_MOUSE = RegisterWindowMessage(L"MSIMEMouseOperation"); } QWinInputContext::~QWinInputContext() @@ -337,26 +309,13 @@ static void notifyIME(HIMC imc, DWORD dwAction, DWORD dwIndex, DWORD dwValue) ImmNotifyIME(imc, dwAction, dwIndex, dwValue); } -static LONG getCompositionString(HIMC himc, DWORD dwIndex, LPVOID lpbuf, DWORD dBufLen, bool *unicode = 0) +static LONG getCompositionString(HIMC himc, DWORD dwIndex, LPVOID lpbuf, DWORD dBufLen) { LONG len = 0; - if (unicode) - *unicode = true; if (aimm) aimm->GetCompositionStringW(himc, dwIndex, dBufLen, &len, lpbuf); else - { - if(QSysInfo::WindowsVersion != QSysInfo::WV_95) { - len = ImmGetCompositionStringW(himc, dwIndex, lpbuf, dBufLen); - } -#if !defined(Q_WS_WINCE) - else { - len = ImmGetCompositionStringA(himc, dwIndex, lpbuf, dBufLen); - if (unicode) - *unicode = false; - } -#endif - } + len = ImmGetCompositionString(himc, dwIndex, lpbuf, dBufLen); return len; } @@ -367,29 +326,28 @@ static int getCursorPosition(HIMC himc) static QString getString(HIMC himc, DWORD dwindex, int *selStart = 0, int *selLength = 0) { - static char *buffer = 0; + static wchar_t *buffer = 0; static int buflen = 0; int len = getCompositionString(himc, dwindex, 0, 0) + 1; if (!buffer || len > buflen) { delete [] buffer; buflen = qMin(len, 256); - buffer = new char[buflen]; + buffer = new wchar_t[buflen]; } - bool unicode = true; - len = getCompositionString(himc, dwindex, buffer, buflen, &unicode); + len = getCompositionString(himc, dwindex, buffer, buflen * sizeof(wchar_t)); if (selStart) { - static char *attrbuffer = 0; + static wchar_t *attrbuffer = 0; static int attrbuflen = 0; int attrlen = getCompositionString(himc, dwindex, 0, 0) + 1; if (!attrbuffer || attrlen> attrbuflen) { delete [] attrbuffer; attrbuflen = qMin(attrlen, 256); - attrbuffer = new char[attrbuflen]; + attrbuffer = new wchar_t[attrbuflen]; } - attrlen = getCompositionString(himc, GCS_COMPATTR, attrbuffer, attrbuflen); + attrlen = getCompositionString(himc, GCS_COMPATTR, attrbuffer, attrbuflen * sizeof(wchar_t)); *selStart = attrlen+1; *selLength = -1; for (int i = 0; i < attrlen; i++) { @@ -403,18 +361,8 @@ static QString getString(HIMC himc, DWORD dwindex, int *selStart = 0, int *selLe if (len <= 0) return QString(); - if (unicode) { - return QString((QChar *)buffer, len/sizeof(QChar)); - } - else { - buffer[len] = 0; - WCHAR *wc = new WCHAR[len+1]; - int l = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, - buffer, len, wc, len+1); - QString res = QString((QChar *)wc, l); - delete [] wc; - return res; - } + + return QString((QChar*)buffer, len / sizeof(QChar)); } void QWinInputContext::TranslateMessage(const MSG *msg) @@ -428,11 +376,7 @@ LRESULT QWinInputContext::DefWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPAR LRESULT retval; if (!aimm || aimm->OnDefWindowProc(hwnd, msg, wParam, lParam, &retval) != S_OK) { - QT_WA({ - retval = ::DefWindowProc(hwnd, msg, wParam, lParam); - } , { - retval = ::DefWindowProcA(hwnd,msg, wParam, lParam); - }); + retval = ::DefWindowProc(hwnd, msg, wParam, lParam); } return retval; } @@ -454,21 +398,13 @@ void QWinInputContext::update() HFONT hf; hf = f.handle(); - QT_WA({ - LOGFONT lf; - if (GetObject(hf, sizeof(lf), &lf)) - if (aimm) - aimm->SetCompositionFontW(imc, &lf); - else - ImmSetCompositionFont(imc, &lf); - } , { - LOGFONTA lf; - if (GetObjectA(hf, sizeof(lf), &lf)) - if (aimm) - aimm->SetCompositionFontA(imc, &lf); - else - ImmSetCompositionFontA(imc, &lf); - }); + LOGFONT lf; + if (GetObject(hf, sizeof(lf), &lf)) { + if (aimm) + aimm->SetCompositionFontW(imc, &lf); + else + ImmSetCompositionFont(imc, &lf); + } QRect r = w->inputMethodQuery(Qt::ImMicroFocus).toRect(); diff --git a/src/gui/itemviews/qfileiconprovider.cpp b/src/gui/itemviews/qfileiconprovider.cpp index 3f7b53d..506b988 100644 --- a/src/gui/itemviews/qfileiconprovider.cpp +++ b/src/gui/itemviews/qfileiconprovider.cpp @@ -243,10 +243,10 @@ QIcon QFileIconProviderPrivate::getWinIcon(const QFileInfo &fileInfo) const //Get the small icon #ifndef Q_OS_WINCE - val = SHGetFileInfo((const WCHAR *)QDir::toNativeSeparators(fileInfo.filePath()).utf16(), 0, &info, + val = SHGetFileInfo((const wchar_t *)QDir::toNativeSeparators(fileInfo.filePath()).utf16(), 0, &info, sizeof(SHFILEINFO), SHGFI_ICON|SHGFI_SMALLICON|SHGFI_SYSICONINDEX|SHGFI_ADDOVERLAYS); #else - val = SHGetFileInfo((const WCHAR *)QDir::toNativeSeparators(fileInfo.filePath()).utf16(), 0, &info, + val = SHGetFileInfo((const wchar_t *)QDir::toNativeSeparators(fileInfo.filePath()).utf16(), 0, &info, sizeof(SHFILEINFO), SHGFI_SMALLICON|SHGFI_SYSICONINDEX); #endif if (val) { @@ -282,10 +282,10 @@ QIcon QFileIconProviderPrivate::getWinIcon(const QFileInfo &fileInfo) const //Get the big icon #ifndef Q_OS_WINCE - val = SHGetFileInfo((const WCHAR *)QDir::toNativeSeparators(fileInfo.filePath()).utf16(), 0, &info, + val = SHGetFileInfo((const wchar_t *)QDir::toNativeSeparators(fileInfo.filePath()).utf16(), 0, &info, sizeof(SHFILEINFO), SHGFI_ICON|SHGFI_LARGEICON|SHGFI_SYSICONINDEX|SHGFI_ADDOVERLAYS); #else - val = SHGetFileInfo((const WCHAR *)QDir::toNativeSeparators(fileInfo.filePath()).utf16(), 0, &info, + val = SHGetFileInfo((const wchar_t *)QDir::toNativeSeparators(fileInfo.filePath()).utf16(), 0, &info, sizeof(SHFILEINFO), SHGFI_LARGEICON|SHGFI_SYSICONINDEX); #endif if (val) { @@ -357,9 +357,7 @@ QIcon QFileIconProvider::icon(const QFileInfo &info) const if (info.isRoot()) #if defined (Q_WS_WIN) && !defined(Q_WS_WINCE) { - uint type = DRIVE_UNKNOWN; - QT_WA({ type = GetDriveTypeW((wchar_t *)info.absoluteFilePath().utf16()); }, - { type = GetDriveTypeA(info.absoluteFilePath().toLocal8Bit()); }); + UINT type = GetDriveType((wchar_t *)info.absoluteFilePath().utf16()); switch (type) { case DRIVE_REMOVABLE: diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 05d9b3c..15ddce8 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -863,12 +863,6 @@ void QApplicationPrivate::initialize() if (qgetenv("QT_USE_NATIVE_WINDOWS").toInt() > 0) q->setAttribute(Qt::AA_NativeWindows); -#if defined(Q_WS_WIN) - // Alien is not currently working on Windows 98 - if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) - q->setAttribute(Qt::AA_NativeWindows); -#endif - #ifdef Q_WS_WINCE #ifdef QT_AUTO_MAXIMIZE_THRESHOLD autoMaximizeThreshold = QT_AUTO_MAXIMIZE_THRESHOLD; @@ -4414,13 +4408,13 @@ HRESULT qt_CoCreateGuid(GUID* guid) { // We will use the following information to create the GUID // 1. absolute path to application - wchar_t tempFilename[512]; - if (!GetModuleFileNameW(0, tempFilename, 512)) + wchar_t tempFilename[MAX_PATH]; + if (!GetModuleFileName(0, tempFilename, MAX_PATH)) return S_FALSE; - unsigned int hash = qHash(QString::fromUtf16((const unsigned short *) tempFilename)); + unsigned int hash = qHash(QString::fromWCharArray(tempFilename)); guid->Data1 = hash; // 2. creation time of file - QFileInfo info(QString::fromUtf16((const unsigned short *) tempFilename)); + QFileInfo info(QString::fromWCharArray(tempFilename)); guid->Data2 = qHash(info.created().toTime_t()); // 3. current system time guid->Data3 = qHash(QDateTime::currentDateTime().toTime_t()); @@ -4454,10 +4448,10 @@ QSessionManager::QSessionManager(QApplication * app, QString &id, QString &key) GUID guid; CoCreateGuid(&guid); StringFromGUID2(guid, guidstr, 40); - id = QString::fromUtf16((ushort*)guidstr); + id = QString::fromWCharArray(guidstr); CoCreateGuid(&guid); StringFromGUID2(guid, guidstr, 40); - key = QString::fromUtf16((ushort*)guidstr); + key = QString::fromWCharArray(guidstr); #endif d->sessionId = id; d->sessionKey = key; diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index bb7d931..e1af0f7 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -145,24 +145,6 @@ typedef struct tagTOUCHINPUT #endif -#ifndef FLASHW_STOP -typedef struct { - UINT cbSize; - HWND hwnd; - DWORD dwFlags; - UINT uCount; - DWORD dwTimeout; -} FLASHWINFO, *PFLASHWINFO; -#define FLASHW_STOP 0 -#define FLASHW_CAPTION 0x00000001 -#define FLASHW_TRAY 0x00000002 -#define FLASHW_ALL (FLASHW_CAPTION | FLASHW_TRAY) -#define FLASHW_TIMER 0x00000004 -#define FLASHW_TIMERNOFG 0x0000000C -#endif /* FLASHW_STOP */ -typedef BOOL (WINAPI *PtrFlashWindowEx)(PFLASHWINFO pfwi); -static PtrFlashWindowEx pFlashWindowEx = 0; - #include #include #include @@ -272,10 +254,6 @@ QTabletDeviceData currentTabletPointer; // from qregion_win.cpp extern HRGN qt_tryCreateRegion(QRegion::RegionType type, int left, int top, int right, int bottom); -Q_CORE_EXPORT bool winPeekMessage(MSG* msg, HWND hWnd, UINT wMsgFilterMin, - UINT wMsgFilterMax, UINT wRemoveMsg); -Q_CORE_EXPORT bool winPostMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); - // support for on-the-fly changes of the XP theme engine #ifndef WM_THEMECHANGED #define WM_THEMECHANGED 0x031A @@ -302,7 +280,7 @@ Q_CORE_EXPORT bool winPostMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPa #define GET_KEYSTATE_WPARAM(wParam) (LOWORD(wParam)) #endif -// support for multi-media-keys on ME/2000/XP +// support for multi-media-keys #ifndef WM_APPCOMMAND #define WM_APPCOMMAND 0x0319 @@ -375,8 +353,6 @@ Q_CORE_EXPORT bool winPostMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPa #endif // WM_APPCOMMAND -static UINT WM95_MOUSEWHEEL = 0; - #if (_WIN32_WINNT < 0x0400) // This struct is defined in winuser.h if the _WIN32_WINNT >= 0x0400 -- in the // other cases we have to define it on our own. @@ -543,14 +519,13 @@ static void qt_set_windows_color_resources() pal.setColor(QPalette::Inactive, QPalette::Light, pal.light().color()); pal.setColor(QPalette::Inactive, QPalette::Dark, pal.dark().color()); - if (QSysInfo::WindowsVersion != QSysInfo::WV_NT && QSysInfo::WindowsVersion != QSysInfo::WV_95) { - if (pal.midlight() == pal.button()) - pal.setColor(QPalette::Midlight, pal.button().color().lighter(110)); - if (pal.background() != pal.base()) { - pal.setColor(QPalette::Inactive, QPalette::Highlight, pal.color(QPalette::Inactive, QPalette::Window)); - pal.setColor(QPalette::Inactive, QPalette::HighlightedText, pal.color(QPalette::Inactive, QPalette::Text)); - } + if (pal.midlight() == pal.button()) + pal.setColor(QPalette::Midlight, pal.button().color().lighter(110)); + if (pal.background() != pal.base()) { + pal.setColor(QPalette::Inactive, QPalette::Highlight, pal.color(QPalette::Inactive, QPalette::Window)); + pal.setColor(QPalette::Inactive, QPalette::HighlightedText, pal.color(QPalette::Inactive, QPalette::Text)); } + const QColor bg = pal.background().color(); const QColor fg = pal.foreground().color(), btn = pal.button().color(); QColor disabled((fg.red()+btn.red())/2,(fg.green()+btn.green())/2, @@ -601,35 +576,18 @@ static void qt_set_windows_color_resources() static void qt_set_windows_font_resources() { #ifndef Q_WS_WINCE - QFont menuFont; - QFont messageFont; - QFont statusFont; - QFont titleFont; - QFont iconTitleFont; - QT_WA({ - NONCLIENTMETRICS ncm; - ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICS, lfMessageFont) + sizeof(LOGFONTW); - SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize , &ncm, 0); - menuFont = qt_LOGFONTtoQFont(ncm.lfMenuFont,true); - messageFont = qt_LOGFONTtoQFont(ncm.lfMessageFont,true); - statusFont = qt_LOGFONTtoQFont(ncm.lfStatusFont,true); - titleFont = qt_LOGFONTtoQFont(ncm.lfCaptionFont,true); - LOGFONTW lfIconTitleFont; - SystemParametersInfoW(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0); - iconTitleFont = qt_LOGFONTtoQFont(lfIconTitleFont,true); - } , { - // A version - NONCLIENTMETRICSA ncm; - ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICSA, lfMessageFont) + sizeof(LOGFONTA); - SystemParametersInfoA(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0); - menuFont = qt_LOGFONTtoQFont((LOGFONT&)ncm.lfMenuFont,true); - messageFont = qt_LOGFONTtoQFont((LOGFONT&)ncm.lfMessageFont,true); - statusFont = qt_LOGFONTtoQFont((LOGFONT&)ncm.lfStatusFont,true); - titleFont = qt_LOGFONTtoQFont((LOGFONT&)ncm.lfCaptionFont,true); - LOGFONTA lfIconTitleFont; - SystemParametersInfoA(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0); - iconTitleFont = qt_LOGFONTtoQFont((LOGFONT&)lfIconTitleFont,true); - }); + NONCLIENTMETRICS ncm; + ncm.cbSize = FIELD_OFFSET(NONCLIENTMETRICS, lfMessageFont) + sizeof(LOGFONT); + SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize , &ncm, 0); + + QFont menuFont = qt_LOGFONTtoQFont(ncm.lfMenuFont, true); + QFont messageFont = qt_LOGFONTtoQFont(ncm.lfMessageFont, true); + QFont statusFont = qt_LOGFONTtoQFont(ncm.lfStatusFont, true); + QFont titleFont = qt_LOGFONTtoQFont(ncm.lfCaptionFont, true); + + LOGFONT lfIconTitleFont; + SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0); + QFont iconTitleFont = qt_LOGFONTtoQFont(lfIconTitleFont, true); QApplication::setFont(menuFont, "QMenu"); QApplication::setFont(menuFont, "QMenuBar"); @@ -657,26 +615,13 @@ static void qt_set_windows_font_resources() static void qt_win_read_cleartype_settings() { + UINT result = 0; #ifdef Q_OS_WINCE - UINT result; - BOOL ok; - ok = SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &result, 0); - if (ok) - qt_cleartype_enabled = result; + if (SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &result, 0)) + qt_cleartype_enabled = result; #else - QT_WA({ - UINT result; - BOOL ok; - ok = SystemParametersInfoW(SPI_GETFONTSMOOTHINGTYPE, 0, &result, 0); - if (ok) - qt_cleartype_enabled = (result == FE_FONTSMOOTHINGCLEARTYPE); - }, { - UINT result; - BOOL ok; - ok = SystemParametersInfoA(SPI_GETFONTSMOOTHINGTYPE, 0, &result, 0); - if (ok) - qt_cleartype_enabled = (result == FE_FONTSMOOTHINGCLEARTYPE); - }); + if (SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0, &result, 0)) + qt_cleartype_enabled = (result == FE_FONTSMOOTHINGCLEARTYPE); #endif } @@ -694,10 +639,10 @@ void QApplicationPrivate::initializeWidgetPaletteHash() QPalette pal = *QApplicationPrivate::sys_pal; QColor menuCol(qt_colorref2qrgb(GetSysColor(COLOR_MENU))); QColor menuText(qt_colorref2qrgb(GetSysColor(COLOR_MENUTEXT))); - BOOL isFlat = 0; + BOOL isFlat = false; if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)) - SystemParametersInfo(0x1022 /*SPI_GETFLATMENU*/, 0, &isFlat, 0); + SystemParametersInfo(SPI_GETFLATMENU, 0, &isFlat, 0); QPalette menu(pal); // we might need a special color group for the menu. menu.setColor(QPalette::Active, QPalette::Button, menuCol); @@ -712,8 +657,7 @@ void QApplicationPrivate::initializeWidgetPaletteHash() QColor(qt_colorref2qrgb(GetSysColor( (QSysInfo::WindowsVersion >= QSysInfo::WV_XP && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based) - && isFlat ? COLOR_MENUHILIGHT - : COLOR_HIGHLIGHT)))); + && isFlat ? COLOR_MENUHILIGHT : COLOR_HIGHLIGHT)))); menu.setColor(QPalette::Disabled, QPalette::HighlightedText, disabled); menu.setColor(QPalette::Disabled, QPalette::Button, menu.color(QPalette::Active, QPalette::Button)); @@ -729,10 +673,8 @@ void QApplicationPrivate::initializeWidgetPaletteHash() menu.color(QPalette::Active, QPalette::Highlight)); menu.setColor(QPalette::Inactive, QPalette::HighlightedText, menu.color(QPalette::Active, QPalette::HighlightedText)); - - if (QSysInfo::WindowsVersion != QSysInfo::WV_NT && QSysInfo::WindowsVersion != QSysInfo::WV_95) - menu.setColor(QPalette::Inactive, QPalette::ButtonText, - pal.color(QPalette::Inactive, QPalette::Dark)); + menu.setColor(QPalette::Inactive, QPalette::ButtonText, + pal.color(QPalette::Inactive, QPalette::Dark)); QApplication::setPalette(menu, "QMenu"); if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP @@ -749,15 +691,10 @@ void QApplicationPrivate::initializeWidgetPaletteHash() qt_init() - initializes Qt for Windows *****************************************************************************/ -typedef BOOL (WINAPI *PtrUpdateLayeredWindow)(HWND hwnd, HDC hdcDst, const POINT *pptDst, - const SIZE *psize, HDC hdcSrc, const POINT *pptSrc, COLORREF crKey, - const Q_BLENDFUNCTION *pblend, DWORD dwflags); - typedef BOOL (WINAPI *PtrSetProcessDPIAware) (VOID); - -static PtrUpdateLayeredWindow ptrUpdateLayeredWindow = 0; static PtrSetProcessDPIAware ptrSetProcessDPIAware = 0; - +PtrUpdateLayeredWindow ptrUpdateLayeredWindow = 0; +PtrUpdateLayeredWindowIndirect ptrUpdateLayeredWindowIndirect = 0; static BOOL WINAPI qt_updateLayeredWindowIndirect(HWND hwnd, const Q_UPDATELAYEREDWINDOWINFO *info) { return (*ptrUpdateLayeredWindow)(hwnd, info->hdcDst, info->pptDst, info->psize, info->hdcSrc, @@ -822,46 +759,30 @@ void qt_init(QApplicationPrivate *priv, int) #endif qApp->setObjectName(priv->appName()); -#if !defined(Q_WS_WINCE) // default font - HFONT hfont = (HFONT)GetStockObject(DEFAULT_GUI_FONT); - QFont f(QLatin1String("MS Sans Serif"),8); - int result = 0; - QT_WA({ - LOGFONT lf; - if (result = GetObject(hfont, sizeof(lf), &lf)) - f = qt_LOGFONTtoQFont((LOGFONT&)lf,true); - } , { - LOGFONTA lf; - if (result = GetObjectA(hfont, sizeof(lf), &lf)) - f = qt_LOGFONTtoQFont((LOGFONT&)lf,true); - }); - if (result - && QSysInfo::WindowsVersion >= QSysInfo::WV_2000 - && QSysInfo::WindowsVersion <= QSysInfo::WV_NT_based - && f.family() == QLatin1String("MS Shell Dlg")) - f.setFamily(QLatin1String("MS Shell Dlg 2")); - QApplicationPrivate::setSystemFont(f); -#else //Q_WS_WINCE - LOGFONT lf; - HGDIOBJ stockFont = GetStockObject(SYSTEM_FONT); - int result = 0; - result = GetObject(stockFont, sizeof(lf), &lf); - QFont font = qt_LOGFONTtoQFont(lf, true); - if (result) - QApplicationPrivate::setSystemFont(font); -#endif //Q_WS_WINCE +#ifndef Q_WS_WINCE + HGDIOBJ stockFont = GetStockObject(DEFAULT_GUI_FONT); +#else + HGDIOBJ stockFont = GetStockObject(SYSTEM_FONT); +#endif + + LOGFONT lf; + GetObject(stockFont, sizeof(lf), &lf); + QFont systemFont = qt_LOGFONTtoQFont(lf, true); + +#ifndef Q_WS_WINCE + if (systemFont.family() == QLatin1String("MS Shell Dlg")) { + systemFont.setFamily(QLatin1String("MS Shell Dlg 2")); + } +#endif + + QApplicationPrivate::setSystemFont(systemFont); // QFont::locale_init(); ### Uncomment when it does something on Windows if (QApplication::desktopSettingsAware()) qt_set_windows_resources(); - QT_WA({ - WM95_MOUSEWHEEL = RegisterWindowMessage(L"MSWHEEL_ROLLMSG"); - } , { - WM95_MOUSEWHEEL = RegisterWindowMessageA("MSWHEEL_ROLLMSG"); - }); initWinTabFunctions(); QApplicationPrivate::inputContext = new QWinInputContext(0); @@ -963,7 +884,7 @@ const QString qt_reg_winclass(QWidget *w) // register window class if (w->inherits("QTipLabel") || w->inherits("QAlphaWidget")) { if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)) { - style |= 0x00020000; // CS_DROPSHADOW + style |= CS_DROPSHADOW; } cname = QLatin1String("QToolTip"); } else { @@ -981,7 +902,7 @@ const QString qt_reg_winclass(QWidget *w) // register window class #endif if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)) - style |= 0x00020000; // CS_DROPSHADOW + style |= CS_DROPSHADOW; icon = false; } else { cname = QLatin1String("QWidget"); @@ -1001,10 +922,10 @@ const QString qt_reg_winclass(QWidget *w) // register window class // unique ID on WinCE to make sure we can // move the windows to the front when starting // a second instance. - wchar_t uniqueAppID[256]; - GetModuleFileNameW(0, uniqueAppID, 255); - cname = QString::number(RegisterWindowMessageW( - (const wchar_t *) QString::fromUtf16((const ushort *)uniqueAppID).toLower().replace(QLatin1Char('\\'), + wchar_t uniqueAppID[MAX_PATH]; + GetModuleFileName(0, uniqueAppID, MAX_PATH); + cname = QString::number(RegisterWindowMessage( + (const wchar_t *) QString::fromWCharArray(uniqueAppID).toLower().replace(QLatin1Char('\\'), QLatin1Char('_')).utf16())); #endif @@ -1016,15 +937,9 @@ const QString qt_reg_winclass(QWidget *w) // register window class static int classExists = -1; if (classExists == -1) { - QT_WA({ - WNDCLASS wcinfo; - classExists = GetClassInfo(qWinAppInst(), (TCHAR*)cname.utf16(), &wcinfo); - classExists = classExists && wcinfo.lpfnWndProc != QtWndProc; - }, { - WNDCLASSA wcinfo; - classExists = GetClassInfoA(qWinAppInst(), cname.toLatin1(), &wcinfo); - classExists = classExists && wcinfo.lpfnWndProc != QtWndProc; - }); + WNDCLASS wcinfo; + classExists = GetClassInfo((HINSTANCE)qWinAppInst(), (wchar_t*)cname.utf16(), &wcinfo); + classExists = classExists && wcinfo.lpfnWndProc != QtWndProc; } if (classExists) @@ -1033,69 +948,31 @@ const QString qt_reg_winclass(QWidget *w) // register window class if (winclassNames()->contains(cname)) // already registered in our list return cname; - ATOM atom; + WNDCLASS wc; + wc.style = style; + wc.lpfnWndProc = (WNDPROC)QtWndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = qWinAppInst(); + if (icon) { + wc.hIcon = (HICON)LoadImage(qWinAppInst(), L"IDI_ICON1", IMAGE_ICON, 0, 0, LR_DEFAULTSIZE); #ifndef Q_WS_WINCE - HBRUSH bgBrush = (HBRUSH)GetSysColorBrush(COLOR_WINDOW); - QT_WA({ - WNDCLASS wc; - wc.style = style; - wc.lpfnWndProc = (WNDPROC)QtWndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = qWinAppInst(); - if (icon) { - wc.hIcon = LoadIcon(qWinAppInst(), L"IDI_ICON1"); - if (!wc.hIcon) - wc.hIcon = LoadIcon(0, IDI_APPLICATION); - } else { - wc.hIcon = 0; - } - wc.hCursor = 0; - wc.hbrBackground= bgBrush; - wc.lpszMenuName = 0; - wc.lpszClassName= (TCHAR*)cname.utf16(); - atom = RegisterClass(&wc); - } , { - WNDCLASSA wc; - wc.style = style; - wc.lpfnWndProc = (WNDPROC)QtWndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = qWinAppInst(); - if (icon) { - wc.hIcon = LoadIconA(qWinAppInst(), (char*)"IDI_ICON1"); - if (!wc.hIcon) - wc.hIcon = LoadIconA(0, (char*)IDI_APPLICATION); - } else { - wc.hIcon = 0; - } - wc.hCursor = 0; - wc.hbrBackground= bgBrush; - wc.lpszMenuName = 0; - QByteArray tempArray = cname.toLatin1(); - wc.lpszClassName= tempArray; - atom = RegisterClassA(&wc); - }); + if (!wc.hIcon) + wc.hIcon = (HICON)LoadImage(0, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED); +#endif + } else { + wc.hIcon = 0; + } + wc.hCursor = 0; +#ifndef Q_WS_WINCE + wc.hbrBackground = (HBRUSH)GetSysColorBrush(COLOR_WINDOW); #else - WNDCLASS wc; - wc.style = style; - wc.lpfnWndProc = (WNDPROC)QtWndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = qWinAppInst(); - if (icon) { - wc.hIcon = LoadIcon(qWinAppInst(), L"IDI_ICON1"); -// if (!wc.hIcon) -// wc.hIcon = LoadIcon(0, IDI_APPLICATION); - } else { - wc.hIcon = 0; - } - wc.hCursor = 0; - wc.hbrBackground= 0; - wc.lpszMenuName = 0; - wc.lpszClassName= (TCHAR*)cname.utf16(); - atom = RegisterClass(&wc); + wc.hbrBackground = 0; #endif + wc.lpszMenuName = 0; + wc.lpszClassName = (wchar_t*)cname.utf16(); + + ATOM atom = RegisterClass(&wc); #ifndef QT_NO_DEBUG if (!atom) @@ -1117,11 +994,7 @@ static void unregWinClasses() WinClassNameHash *hash = winclassNames(); QHash::ConstIterator it = hash->constBegin(); while (it != hash->constEnd()) { - QT_WA({ - UnregisterClass((TCHAR*)it.key().utf16(), qWinAppInst()); - } , { - UnregisterClassA(it.key().toLatin1(), qWinAppInst()); - }); + UnregisterClass((wchar_t*)it.key().utf16(), qWinAppInst()); ++it; } hash->clear(); @@ -1338,16 +1211,10 @@ void QApplication::beep() static void alert_widget(QWidget *widget, int duration) { - bool stopFlash = duration < 0; - - if (!pFlashWindowEx) { #ifndef Q_OS_WINCE - QLibrary themeLib(QLatin1String("user32")); - pFlashWindowEx = (PtrFlashWindowEx)themeLib.resolve("FlashWindowEx"); -#endif - } + bool stopFlash = duration < 0; - if (pFlashWindowEx && widget && (!widget->isActiveWindow() || stopFlash)) { + if (widget && (!widget->isActiveWindow() || stopFlash)) { DWORD timeOut = GetCaretBlinkTime(); if (timeOut <= 0) timeOut = 250; @@ -1365,8 +1232,9 @@ static void alert_widget(QWidget *widget, int duration) info.dwTimeout = stopFlash ? 0 : timeOut; info.uCount = stopFlash ? 0 : flashCount; - pFlashWindowEx(&info); + FlashWindowEx(&info); } +#endif } void QApplication::alert(QWidget *widget, int duration) @@ -1727,7 +1595,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam // Sometimes we only get a WM_MOUSEMOVE message // and sometimes we get both a WM_MOUSEMOVE and // a WM_LBUTTONDOWN/UP, this creates a spurious mouse - // press/release event, using the winPeekMessage + // press/release event, using the PeekMessage // will help us fix this. This leaves us with a // question: // This effectively kills using the mouse AND the @@ -1737,16 +1605,14 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam bool is_mouse_move = (message == WM_MOUSEMOVE); if (is_mouse_move) { MSG msg1; - if (winPeekMessage(&msg1, msg.hwnd, WM_MOUSEFIRST, - WM_MOUSELAST, PM_NOREMOVE)) + if (PeekMessage(&msg1, msg.hwnd, WM_MOUSEFIRST, + WM_MOUSELAST, PM_NOREMOVE)) next_is_button = (msg1.message == WM_LBUTTONUP || msg1.message == WM_LBUTTONDOWN); } if (!is_mouse_move || (is_mouse_move && !next_is_button)) qt_tabletChokeMouse = false; } - } else if (message == WM95_MOUSEWHEEL) { - result = widget->translateWheelEvent(msg); } else { switch (message) { case WM_TOUCH: @@ -1777,7 +1643,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam case WM_IME_KEYDOWN: case WM_CHAR: { MSG msg1; - bool anyMsg = winPeekMessage(&msg1, msg.hwnd, 0, 0, PM_NOREMOVE); + bool anyMsg = PeekMessage(&msg1, msg.hwnd, 0, 0, PM_NOREMOVE); if (anyMsg && msg1.message == WM_DEADCHAR) { result = true; // consume event since there is a dead char next break; @@ -1977,11 +1843,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam #ifndef QT_NO_WHATSTHIS QWhatsThis::enterWhatsThisMode(); #endif - QT_WA({ - DefWindowProc(hwnd, WM_NCPAINT, 1, 0); - } , { - DefWindowProcA(hwnd, WM_NCPAINT, 1, 0); - }); + DefWindowProc(hwnd, WM_NCPAINT, 1, 0); break; #if defined(QT_NON_COMMERCIAL) QT_NC_SYSCOMMAND @@ -2043,8 +1905,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam break; if (!msg.wParam) { - QString area = QT_WA_INLINE(QString::fromUtf16((unsigned short *)msg.lParam), - QString::fromLocal8Bit((char*)msg.lParam)); + QString area = QString::fromWCharArray((wchar_t*)msg.lParam); if (area == QLatin1String("intl")) { QLocalePrivate::updateSystemPrivate(); if (!widget->testAttribute(Qt::WA_SetLocale)) @@ -2422,11 +2283,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam text = widget->objectName(); ret = qMin(wParam - 1, text.size()); text.resize(ret); - QT_WA({ - memcpy((void *)lParam, text.utf16(), (text.size() + 1) * 2); - }, { - memcpy((void *)lParam, text.toLocal8Bit().data(), text.size() + 1); - }); + memcpy((void *)lParam, text.utf16(), (text.size() + 1) * sizeof(ushort)); delete acc; } if (!ret) { @@ -2514,11 +2371,11 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam #ifndef Q_WS_WINCE case WM_INPUTLANGCHANGE: { - char info[7]; - if (!GetLocaleInfoA(MAKELCID(lParam, SORT_DEFAULT), LOCALE_IDEFAULTANSICODEPAGE, info, 6)) { + wchar_t info[7]; + if (!GetLocaleInfo(MAKELCID(lParam, SORT_DEFAULT), LOCALE_IDEFAULTANSICODEPAGE, info, 6)) { inputcharset = CP_ACP; } else { - inputcharset = QString::fromLatin1(info).toInt(); + inputcharset = QString::fromWCharArray(info).toInt(); } QKeyMapper::changeKeyboard(); break; @@ -2714,8 +2571,7 @@ bool qt_try_modal(QWidget *widget, MSG *msg, int& ret) if (type != WM_NCHITTEST) #endif if ((type >= WM_MOUSEFIRST && type <= WM_MOUSELAST) || - type == WM_MOUSEWHEEL || type == (int)WM95_MOUSEWHEEL || - type == WM_MOUSEHWHEEL || + type == WM_MOUSEWHEEL || type == WM_MOUSEHWHEEL || type == WM_MOUSELEAVE || (type >= WM_KEYFIRST && type <= WM_KEYLAST) #ifndef Q_WS_WINCE @@ -2955,19 +2811,10 @@ void qt_win_eatMouseMove() // reset button state MSG msg = {0, 0, 0, 0, 0, 0, 0}; - QT_WA( { - while (PeekMessage(&msg, 0, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE)) - ; - if (msg.message == WM_MOUSEMOVE) - PostMessage(msg.hwnd, msg.message, 0, msg.lParam); - }, { - MSG msg; - msg.message = 0; - while (PeekMessageA(&msg, 0, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE)) - ; - if (msg.message == WM_MOUSEMOVE) - PostMessageA(msg.hwnd, msg.message, 0, msg.lParam); - } ); + while (PeekMessage(&msg, 0, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE)) + ; + if (msg.message == WM_MOUSEMOVE) + PostMessage(msg.hwnd, msg.message, 0, msg.lParam); } // In DnD, the mouse release event never appears, so the @@ -3002,8 +2849,8 @@ bool QETWidget::translateMouseEvent(const MSG &msg) // Compress mouse move events if (msg.message == WM_MOUSEMOVE) { MSG mouseMsg; - while (winPeekMessage(&mouseMsg, msg.hwnd, WM_MOUSEFIRST, - WM_MOUSELAST, PM_NOREMOVE)) { + while (PeekMessage(&mouseMsg, msg.hwnd, WM_MOUSEFIRST, + WM_MOUSELAST, PM_NOREMOVE)) { if (mouseMsg.message == WM_MOUSEMOVE) { #define PEEKMESSAGE_IS_BROKEN 1 #ifdef PEEKMESSAGE_IS_BROKEN @@ -3014,12 +2861,12 @@ bool QETWidget::translateMouseEvent(const MSG &msg) // key release events (kls 2003-05-13): MSG keyMsg; bool done = false; - while (winPeekMessage(&keyMsg, 0, WM_KEYFIRST, WM_KEYLAST, - PM_NOREMOVE)) { + while (PeekMessage(&keyMsg, 0, WM_KEYFIRST, WM_KEYLAST, + PM_NOREMOVE)) { if (keyMsg.time < mouseMsg.time) { if ((keyMsg.lParam & 0xC0000000) == 0x40000000) { - winPeekMessage(&keyMsg, 0, keyMsg.message, - keyMsg.message, PM_REMOVE); + PeekMessage(&keyMsg, 0, keyMsg.message, + keyMsg.message, PM_REMOVE); } else { done = true; break; @@ -3045,8 +2892,8 @@ bool QETWidget::translateMouseEvent(const MSG &msg) msgPtr->wParam = mouseMsg.wParam; msgPtr->pt = mouseMsg.pt; // Remove the mouse move message - winPeekMessage(&mouseMsg, msg.hwnd, WM_MOUSEMOVE, - WM_MOUSEMOVE, PM_REMOVE); + PeekMessage(&mouseMsg, msg.hwnd, WM_MOUSEMOVE, + WM_MOUSEMOVE, PM_REMOVE); } else { break; // there was no more WM_MOUSEMOVE event } @@ -3260,7 +3107,7 @@ bool QETWidget::translateMouseEvent(const MSG &msg) POINT widgetpt = gpos; ScreenToClient(hwndTarget, &widgetpt); LPARAM lParam = MAKELPARAM(widgetpt.x, widgetpt.y); - winPostMessage(hwndTarget, msg.message, msg.wParam, lParam); + PostMessage(hwndTarget, msg.message, msg.wParam, lParam); } } else if (type == QEvent::MouseButtonRelease && button == Qt::RightButton && QApplication::activePopupWidget() == activePopupWidget) { @@ -3627,14 +3474,8 @@ static void initWinTabFunctions() QLibrary library(QLatin1String("wintab32")); if (library.load()) { - QT_WA({ - ptrWTInfo = (PtrWTInfo)library.resolve("WTInfoW"); - ptrWTGet = (PtrWTGet)library.resolve("WTGetW"); - } , { - ptrWTInfo = (PtrWTInfo)library.resolve("WTInfoA"); - ptrWTGet = (PtrWTGet)library.resolve("WTGetA"); - }); - + ptrWTInfo = (PtrWTInfo)library.resolve("WTInfoW"); + ptrWTGet = (PtrWTGet)library.resolve("WTGetW"); ptrWTEnable = (PtrWTEnable)library.resolve("WTEnable"); ptrWTOverlap = (PtrWTEnable)library.resolve("WTOverlap"); ptrWTPacketsGet = (PtrWTPacketsGet)library.resolve("WTPacketsGet"); @@ -3861,11 +3702,7 @@ void QApplication::setWheelScrollLines(int n) #ifdef SPI_SETWHEELSCROLLLINES if (n < 0) n = 0; - QT_WA({ - SystemParametersInfo(SPI_SETWHEELSCROLLLINES, (uint)n, 0, 0); - } , { - SystemParametersInfoA(SPI_SETWHEELSCROLLLINES, (uint)n, 0, 0); - }); + SystemParametersInfo(SPI_SETWHEELSCROLLLINES, (uint)n, 0, 0); #else QApplicationPrivate::wheel_scroll_lines = n; #endif @@ -3875,11 +3712,7 @@ int QApplication::wheelScrollLines() { #ifdef SPI_GETWHEELSCROLLLINES uint i = 3; - QT_WA({ - SystemParametersInfo(SPI_GETWHEELSCROLLLINES, sizeof(uint), &i, 0); - } , { - SystemParametersInfoA(SPI_GETWHEELSCROLLLINES, sizeof(uint), &i, 0); - }); + SystemParametersInfo(SPI_GETWHEELSCROLLLINES, sizeof(uint), &i, 0); if (i > INT_MAX) i = INT_MAX; return i; @@ -3924,8 +3757,7 @@ bool QApplication::isEffectEnabled(Qt::UIEffect effect) if (QColormap::instance().depth() < 16) return false; - if (!effect_override && desktopSettingsAware() - && !(QSysInfo::WindowsVersion == QSysInfo::WV_95 || QSysInfo::WindowsVersion == QSysInfo::WV_NT)) { + if (!effect_override && desktopSettingsAware()) { // we know that they can be used when we are here BOOL enabled = false; UINT api; @@ -3934,33 +3766,22 @@ bool QApplication::isEffectEnabled(Qt::UIEffect effect) api = SPI_GETMENUANIMATION; break; case Qt::UI_FadeMenu: - if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) - return false; api = SPI_GETMENUFADE; break; case Qt::UI_AnimateCombo: api = SPI_GETCOMBOBOXANIMATION; break; case Qt::UI_AnimateTooltip: - if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) - api = SPI_GETMENUANIMATION; - else - api = SPI_GETTOOLTIPANIMATION; + api = SPI_GETTOOLTIPANIMATION; break; case Qt::UI_FadeTooltip: - if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) - return false; api = SPI_GETTOOLTIPFADE; break; default: api = SPI_GETUIEFFECTS; break; } - QT_WA({ - SystemParametersInfo(api, 0, &enabled, 0); - } , { - SystemParametersInfoA(api, 0, &enabled, 0); - }); + SystemParametersInfo(api, 0, &enabled, 0); return enabled; } diff --git a/src/gui/kernel/qclipboard_win.cpp b/src/gui/kernel/qclipboard_win.cpp index 09b5448..f5aa088 100644 --- a/src/gui/kernel/qclipboard_win.cpp +++ b/src/gui/kernel/qclipboard_win.cpp @@ -200,7 +200,7 @@ HRESULT QtCeGetClipboard(IDataObject** obj) if (clipData == 0) { clipData = GetClipboardData(CF_UNICODETEXT); if (clipData != 0) - clipText = QString::fromUtf16((unsigned short *)clipData); + clipText = QString::fromWCharArray((wchar_t *)clipData); } else { clipText = QString::fromLatin1((const char*)clipData); } @@ -325,13 +325,7 @@ bool QClipboard::event(QEvent *e) } if (propagate && d->nextClipboardViewer) { - QT_WA({ - SendMessage(d->nextClipboardViewer, m->message, - m->wParam, m->lParam); - } , { - SendMessageA(d->nextClipboardViewer, m->message, - m->wParam, m->lParam); - }); + SendMessage(d->nextClipboardViewer, m->message, m->wParam, m->lParam); } return true; diff --git a/src/gui/kernel/qcursor_win.cpp b/src/gui/kernel/qcursor_win.cpp index f0dc108..db00835 100644 --- a/src/gui/kernel/qcursor_win.cpp +++ b/src/gui/kernel/qcursor_win.cpp @@ -317,54 +317,50 @@ void QCursorData::update() phand_bits, phandm_bits }; - unsigned short *sh; + wchar_t *sh = 0; switch (cshape) { // map to windows cursor case Qt::ArrowCursor: - sh = (unsigned short*)IDC_ARROW; + sh = IDC_ARROW; break; case Qt::UpArrowCursor: - sh = (unsigned short*)IDC_UPARROW; + sh = IDC_UPARROW; break; case Qt::CrossCursor: - sh = (unsigned short*)IDC_CROSS; + sh = IDC_CROSS; break; case Qt::WaitCursor: - sh = (unsigned short*)IDC_WAIT; + sh = IDC_WAIT; break; case Qt::IBeamCursor: - sh = (unsigned short*)IDC_IBEAM; + sh = IDC_IBEAM; break; case Qt::SizeVerCursor: - sh = (unsigned short*)IDC_SIZENS; + sh = IDC_SIZENS; break; case Qt::SizeHorCursor: - sh = (unsigned short*)IDC_SIZEWE; + sh = IDC_SIZEWE; break; case Qt::SizeBDiagCursor: - sh = (unsigned short*)IDC_SIZENESW; + sh = IDC_SIZENESW; break; case Qt::SizeFDiagCursor: - sh = (unsigned short*)IDC_SIZENWSE; + sh = IDC_SIZENWSE; break; case Qt::SizeAllCursor: - sh = (unsigned short*)IDC_SIZEALL; + sh = IDC_SIZEALL; break; case Qt::ForbiddenCursor: - sh = (unsigned short*)IDC_NO; + sh = IDC_NO; break; case Qt::WhatsThisCursor: - sh = (unsigned short*)IDC_HELP; + sh = IDC_HELP; break; case Qt::BusyCursor: - sh = (unsigned short*)IDC_APPSTARTING; + sh = IDC_APPSTARTING; break; case Qt::PointingHandCursor: - if ((QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) > QSysInfo::WV_95 || - (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based) > QSysInfo::WV_NT) { - sh = (unsigned short*)IDC_HAND; - break; - } - // fall through + sh = IDC_HAND; + break; case Qt::BlankCursor: case Qt::SplitVCursor: case Qt::SplitHCursor: @@ -480,13 +476,7 @@ void QCursorData::update() qWarning("QCursor::update: Invalid cursor shape %d", cshape); return; } - // ### From MSDN: - // ### LoadCursor has been superseded by the LoadImage function. - QT_WA({ - hcurs = LoadCursorW(0, reinterpret_cast(sh)); - } , { - hcurs = LoadCursorA(0, reinterpret_cast(sh)); - }); + hcurs = (HCURSOR)LoadImage(0, sh, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED); } QT_END_NAMESPACE diff --git a/src/gui/kernel/qdesktopwidget_win.cpp b/src/gui/kernel/qdesktopwidget_win.cpp index aa290c4..fb176b7 100644 --- a/src/gui/kernel/qdesktopwidget_win.cpp +++ b/src/gui/kernel/qdesktopwidget_win.cpp @@ -152,41 +152,27 @@ void QDesktopWidgetPrivate::init(QDesktopWidget *that) rects = new QVector(); workrects = new QVector(); + screenCount = 0; #ifndef Q_OS_WINCE - if (QSysInfo::WindowsVersion != QSysInfo::WV_95 && QSysInfo::WindowsVersion != QSysInfo::WV_NT) { - screenCount = 0; - // Trying to get the function pointers to Win98/2000 only functions - QLibrary user32Lib(QLatin1String("user32")); - if (!user32Lib.load()) - return; + QLibrary user32Lib(QLatin1String("user32")); + if (user32Lib.load()) { enumDisplayMonitors = (EnumFunc)user32Lib.resolve("EnumDisplayMonitors"); - QT_WA({ - getMonitorInfo = (InfoFunc)user32Lib.resolve("GetMonitorInfoW"); - } , { - getMonitorInfo = (InfoFunc)user32Lib.resolve("GetMonitorInfoA"); - }); - - if (!enumDisplayMonitors || !getMonitorInfo) { - screenCount = GetSystemMetrics(80); // SM_CMONITORS - rects->resize(screenCount); - for (int i = 0; i < screenCount; ++i) - rects->replace(i, that->rect()); - return; - } - // Calls enumCallback - enumDisplayMonitors(0, 0, enumCallback, 0); - enumDisplayMonitors = 0; - getMonitorInfo = 0; - } else { - rects->resize(1); - rects->replace(0, that->rect()); - workrects->resize(1); - workrects->replace(0, that->rect()); + getMonitorInfo = (InfoFunc)user32Lib.resolve("GetMonitorInfoW"); } -#else - screenCount = 0; + if (!enumDisplayMonitors || !getMonitorInfo) { + screenCount = GetSystemMetrics(80); // SM_CMONITORS + rects->resize(screenCount); + for (int i = 0; i < screenCount; ++i) + rects->replace(i, that->rect()); + return; + } + // Calls enumCallback + enumDisplayMonitors(0, 0, enumCallback, 0); + enumDisplayMonitors = 0; + getMonitorInfo = 0; +#else QLibrary coreLib(QLatin1String("coredll")); if (coreLib.load()) { // CE >= 4.0 case @@ -307,70 +293,61 @@ const QRect QDesktopWidget::availableGeometry(int screen) const for(int i=0; i < d->workrects->size(); ++i) qt_get_sip_info((*d->workrects)[i]); #endif - if (QSysInfo::WindowsVersion != QSysInfo::WV_95 && QSysInfo::WindowsVersion != QSysInfo::WV_NT) { - if (screen < 0 || screen >= d->screenCount) - screen = d->primaryScreen; + if (screen < 0 || screen >= d->screenCount) + screen = d->primaryScreen; - return d->workrects->at(screen); - } else { - return d->workrects->at(d->primaryScreen); - } + return d->workrects->at(screen); } const QRect QDesktopWidget::screenGeometry(int screen) const { const QDesktopWidgetPrivate *d = d_func(); - if (QSysInfo::WindowsVersion != QSysInfo::WV_95 && QSysInfo::WindowsVersion != QSysInfo::WV_NT) { - if (screen < 0 || screen >= d->screenCount) - screen = d->primaryScreen; + if (screen < 0 || screen >= d->screenCount) + screen = d->primaryScreen; - return d->rects->at(screen); - } else { - return d->rects->at(d->primaryScreen); - } + return d->rects->at(screen); } int QDesktopWidget::screenNumber(const QWidget *widget) const { Q_D(const QDesktopWidget); - if (QSysInfo::WindowsVersion != QSysInfo::WV_95 && QSysInfo::WindowsVersion != QSysInfo::WV_NT) { - if (!widget) - return d->primaryScreen; - QRect frame = widget->frameGeometry(); - if (!widget->isWindow()) - frame.moveTopLeft(widget->mapToGlobal(QPoint(0,0))); - - int maxSize = -1; - int maxScreen = -1; - - for (int i = 0; i < d->screenCount; ++i) { - QRect sect = d->rects->at(i).intersected(frame); - int size = sect.width() * sect.height(); - if (size > maxSize && sect.width() > 0 && sect.height() > 0) { - maxSize = size; - maxScreen = i; - } - } - return maxScreen; - } else { + if (!widget) return d->primaryScreen; + + QRect frame = widget->frameGeometry(); + if (!widget->isWindow()) + frame.moveTopLeft(widget->mapToGlobal(QPoint(0,0))); + + int maxSize = -1; + int maxScreen = -1; + + for (int i = 0; i < d->screenCount; ++i) { + QRect sect = d->rects->at(i).intersected(frame); + int size = sect.width() * sect.height(); + if (size > maxSize && sect.width() > 0 && sect.height() > 0) { + maxSize = size; + maxScreen = i; + } } + + return maxScreen; } int QDesktopWidget::screenNumber(const QPoint &point) const { Q_D(const QDesktopWidget); + int closestScreen = -1; - if (QSysInfo::WindowsVersion != QSysInfo::WV_95 && QSysInfo::WindowsVersion != QSysInfo::WV_NT) { - int shortestDistance = INT_MAX; - for (int i = 0; i < d->screenCount; ++i) { - int thisDistance = d->pointToRect(point, d->rects->at(i)); - if (thisDistance < shortestDistance) { - shortestDistance = thisDistance; - closestScreen = i; - } + int shortestDistance = INT_MAX; + + for (int i = 0; i < d->screenCount; ++i) { + int thisDistance = d->pointToRect(point, d->rects->at(i)); + if (thisDistance < shortestDistance) { + shortestDistance = thisDistance; + closestScreen = i; } } + return closestScreen; } diff --git a/src/gui/kernel/qdnd_win.cpp b/src/gui/kernel/qdnd_win.cpp index 99c960c..70f89d2 100644 --- a/src/gui/kernel/qdnd_win.cpp +++ b/src/gui/kernel/qdnd_win.cpp @@ -154,9 +154,9 @@ QOleDataObject::GetData(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium) #ifdef QDND_DEBUG qDebug("QOleDataObject::GetData(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium)"); #ifndef Q_OS_WINCE - char buf[256] = {0}; - GetClipboardFormatNameA(pformatetc->cfFormat, buf, 255); - qDebug("CF = %d : %s", pformatetc->cfFormat, buf); + wchar_t buf[256] = {0}; + GetClipboardFormatName(pformatetc->cfFormat, buf, 255); + qDebug("CF = %d : %s", pformatetc->cfFormat, QString::fromWCharArray(buf)); #endif #endif @@ -398,52 +398,47 @@ void QOleDropSource::createCursors() int h = cpm.height(); if (!pm.isNull()) { - int x1 = qMin(-hotSpot.x(),0); - int x2 = qMax(pm.width()-hotSpot.x(),cpm.width()); - int y1 = qMin(-hotSpot.y(),0); - int y2 = qMax(pm.height()-hotSpot.y(),cpm.height()); + int x1 = qMin(-hotSpot.x(), 0); + int x2 = qMax(pm.width() - hotSpot.x(), cpm.width()); + int y1 = qMin(-hotSpot.y(), 0); + int y2 = qMax(pm.height() - hotSpot.y(), cpm.height()); - w = x2-x1+1; - h = y2-y1+1; + w = x2 - x1 + 1; + h = y2 - y1 + 1; } QRect srcRect = pm.rect(); QPoint pmDest = QPoint(qMax(0, -hotSpot.x()), qMax(0, -hotSpot.y())); QPoint newHotSpot = hotSpot; -#if !defined(Q_OS_WINCE) || defined(GWES_ICONCURS) - bool limitedCursorSize = (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) - || (QSysInfo::WindowsVersion == QSysInfo::WV_NT) - || (QSysInfo::WindowsVersion == QSysInfo::WV_CE); - - if (limitedCursorSize) { - // Limited cursor size - int reqw = GetSystemMetrics(SM_CXCURSOR); - int reqh = GetSystemMetrics(SM_CYCURSOR); - - QPoint hotspotInPM = newHotSpot - pmDest; - if (reqw < w) { - // Not wide enough - move objectpm right - qreal r = qreal(newHotSpot.x()) / w; - newHotSpot = QPoint(int(r * reqw), newHotSpot.y()); - if (newHotSpot.x() + cpm.width() > reqw) - newHotSpot.setX(reqw - cpm.width()); - - srcRect = QRect(QPoint(hotspotInPM.x() - newHotSpot.x(), srcRect.top()), QSize(reqw, srcRect.height())); - } - if (reqh < h) { - qreal r = qreal(newHotSpot.y()) / h; - newHotSpot = QPoint(newHotSpot.x(), int(r * reqh)); - if (newHotSpot.y() + cpm.height() > reqh) - newHotSpot.setY(reqh - cpm.height()); - - srcRect = QRect(QPoint(srcRect.left(), hotspotInPM.y() - newHotSpot.y()), QSize(srcRect.width(), reqh)); - } - // Always use system cursor size - w = reqw; - h = reqh; +#if defined(Q_OS_WINCE) + // Limited cursor size + int reqw = GetSystemMetrics(SM_CXCURSOR); + int reqh = GetSystemMetrics(SM_CYCURSOR); + + QPoint hotspotInPM = newHotSpot - pmDest; + if (reqw < w) { + // Not wide enough - move objectpm right + qreal r = qreal(newHotSpot.x()) / w; + newHotSpot = QPoint(int(r * reqw), newHotSpot.y()); + if (newHotSpot.x() + cpm.width() > reqw) + newHotSpot.setX(reqw - cpm.width()); + + srcRect = QRect(QPoint(hotspotInPM.x() - newHotSpot.x(), srcRect.top()), QSize(reqw, srcRect.height())); } + if (reqh < h) { + qreal r = qreal(newHotSpot.y()) / h; + newHotSpot = QPoint(newHotSpot.x(), int(r * reqh)); + if (newHotSpot.y() + cpm.height() > reqh) + newHotSpot.setY(reqh - cpm.height()); + + srcRect = QRect(QPoint(srcRect.left(), hotspotInPM.y() - newHotSpot.y()), QSize(srcRect.width(), reqh)); + } + // Always use system cursor size + w = reqw; + h = reqh; #endif + QPixmap newCursor(w, h); if (!pm.isNull()) { newCursor.fill(QColor(0, 0, 0, 0)); diff --git a/src/gui/kernel/qguifunctions_wince.cpp b/src/gui/kernel/qguifunctions_wince.cpp index c986117..011c726 100644 --- a/src/gui/kernel/qguifunctions_wince.cpp +++ b/src/gui/kernel/qguifunctions_wince.cpp @@ -215,13 +215,7 @@ int qt_wince_GetDIBits(HDC /*hdc*/ , HBITMAP hSourceBitmap, uint, uint, LPVOID l return ret; } -bool qt_wince_TextOutW(HDC hdc, int x, int y, LPWSTR lpString, UINT c) -{ - return ExtTextOutW(hdc, x, y, 0, NULL, lpString, c, NULL); -} - - -HINSTANCE qt_wince_ShellExecute(HWND hwnd, LPCTSTR, LPCTSTR file, LPCTSTR params, LPCTSTR dir, int showCmd) +HINSTANCE qt_wince_ShellExecute(HWND hwnd, LPCWSTR, LPCWSTR file, LPCWSTR params, LPCWSTR dir, int showCmd) { SHELLEXECUTEINFO info; info.hwnd = hwnd; @@ -253,17 +247,11 @@ COLORREF qt_wince_PALETTEINDEX( WORD /*wPaletteIndex*/) return 0; } -BOOL qt_wince_TextOut( HDC hdc, int nXStart, int nYStart, LPCTSTR lpString, int cbString ) -{ - return ExtTextOut( hdc, nXStart, nYStart - 16, 0, NULL, lpString, cbString, NULL ); -} - // Internal Qt ----------------------------------------------------- bool qt_wince_is_platform(const QString &platformString) { - TCHAR tszPlatform[64]; - if (SystemParametersInfo(SPI_GETPLATFORMTYPE, - sizeof(tszPlatform)/sizeof(*tszPlatform),tszPlatform,0)) - if (0 == _tcsicmp(reinterpret_cast (platformString.utf16()), tszPlatform)) + wchar_t tszPlatform[64]; + if (SystemParametersInfo(SPI_GETPLATFORMTYPE, sizeof(tszPlatform) / sizeof(wchar_t), tszPlatform, 0)) + if (0 == _tcsicmp(reinterpret_cast (platformString.utf16()), tszPlatform)) return true; return false; } @@ -316,8 +304,8 @@ void qt_wince_maximize(QWidget *widget) void qt_wince_minimize(HWND hwnd) { - uint exstyle = GetWindowLongW(hwnd, GWL_EXSTYLE); - uint style = GetWindowLongW(hwnd, GWL_STYLE); + uint exstyle = GetWindowLong(hwnd, GWL_EXSTYLE); + uint style = GetWindowLong(hwnd, GWL_STYLE); RECT rect; RECT crect = {0,0,0,0}; GetWindowRect(hwnd, &rect); diff --git a/src/gui/kernel/qguifunctions_wince.h b/src/gui/kernel/qguifunctions_wince.h index bcf2004..234c8c6 100644 --- a/src/gui/kernel/qguifunctions_wince.h +++ b/src/gui/kernel/qguifunctions_wince.h @@ -73,10 +73,6 @@ int qt_wince_GetDIBits(HDC, HBITMAP, uint, uint, void*, LPBITMAPINFO, uint); // QWidget #define SW_SHOWMINIMIZED SW_MINIMIZE -// QPaintEngine -bool qt_wince_TextOutW(HDC, int, int, LPWSTR, UINT); -#define TextOutW(a,b,c,d,e) qt_wince_TextOutW(a,b,c,d,e) - // QRegion #define ALTERNATE 0 #define WINDING 1 @@ -128,7 +124,7 @@ typedef struct tagTTPOLYCURVE #define TT_PRIM_CSPLINE 3 #define ANSI_VAR_FONT 12 -HINSTANCE qt_wince_ShellExecute(HWND hwnd, LPCTSTR operation, LPCTSTR file, LPCTSTR params, LPCTSTR dir, int showCmd); +HINSTANCE qt_wince_ShellExecute(HWND hwnd, LPCWSTR operation, LPCWSTR file, LPCWSTR params, LPCWSTR dir, int showCmd); #define ShellExecute(a,b,c,d,e,f) qt_wince_ShellExecute(a,b,c,d,e,f) @@ -150,8 +146,6 @@ HWND qt_wince_SetClipboardViewer( // Graphics --------------------------------------------------------- COLORREF qt_wince_PALETTEINDEX( WORD wPaletteIndex ); #define PALETTEINDEX(a) qt_wince_PALETTEINDEX(a) -BOOL qt_wince_TextOut( HDC hdc, int nXStart, int nYStart, LPCTSTR lpString, int cbString ); -#define TextOut(a,b,c,d,e) qt_wince_TextOut(a,b,c,d,e) #endif // Q_OS_WINCE #endif // QGUIFUNCTIONS_WCE_H diff --git a/src/gui/kernel/qkeymapper_win.cpp b/src/gui/kernel/qkeymapper_win.cpp index e40dfa0..3d53f31 100644 --- a/src/gui/kernel/qkeymapper_win.cpp +++ b/src/gui/kernel/qkeymapper_win.cpp @@ -57,9 +57,7 @@ QT_BEGIN_NAMESPACE // Implemented elsewhere extern "C" LRESULT CALLBACK QtWndProc(HWND, UINT, WPARAM, LPARAM); -Q_CORE_EXPORT bool winPostMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); -Q_CORE_EXPORT bool winPeekMessage(MSG* msg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, - UINT wRemoveMsg); + extern Q_CORE_EXPORT QLocale qt_localeFromLCID(LCID id); #ifndef LANG_PASHTO #define LANG_PASHTO 0x63 @@ -467,12 +465,7 @@ static inline int toKeyOrUnicode(int vk, int scancode, unsigned char *kbdBuffer, Q_ASSERT(vk > 0 && vk < 256); int code = 0; QChar unicodeBuffer[5]; - int res = 0; - if (QSysInfo::WindowsVersion < QSysInfo::WV_NT) - res = ToAscii(vk, scancode, kbdBuffer, reinterpret_cast(unicodeBuffer), 0); - else - res = ToUnicode(vk, scancode, kbdBuffer, reinterpret_cast(unicodeBuffer), 5, 0); - + int res = ToUnicode(vk, scancode, kbdBuffer, reinterpret_cast(unicodeBuffer), 5, 0); if (res) code = unicodeBuffer[0].toUpper().unicode(); @@ -504,38 +497,6 @@ static inline int asciiToKeycode(char a, int state) return a & 0xff; } -static int inputcharset = CP_ACP; -static inline QChar wmchar_to_unicode(DWORD c) -{ - // qt_winMB2QString is the generalization of this function. - QT_WA({ - return QChar((ushort)c); - } , { - char mb[2]; - mb[0] = c & 0xff; - mb[1] = 0; - WCHAR wc[1]; - MultiByteToWideChar(inputcharset, MB_PRECOMPOSED, mb, -1, wc, 1); - return QChar(wc[0]); - }); -} - -static inline QChar imechar_to_unicode(DWORD c) -{ - // qt_winMB2QString is the generalization of this function. - QT_WA({ - return QChar((ushort)c); - } , { - char mb[3]; - mb[0] = (c >> 8) & 0xff; - mb[1] = c & 0xff; - mb[2] = 0; - WCHAR wc[1]; - MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, mb, -1, wc, 1); - return QChar(wc[0]); - }); -} - static inline bool isModifierKey(int code) { return (code >= Qt::Key_Shift) && (code <= Qt::Key_ScrollLock); @@ -635,43 +596,15 @@ void QKeyMapperPrivate::clearMappings() /* MAKELCID()'s first argument is a WORD, and GetKeyboardLayout() * returns a DWORD. */ -// LCID newLCID = MAKELCID(DWORD(GetKeyboardLayout(0)), SORT_DEFAULT); + + LCID newLCID = MAKELCID((DWORD)GetKeyboardLayout(0), SORT_DEFAULT); // keyboardInputLocale = qt_localeFromLCID(newLCID); - LCID newLCID = MAKELCID( - reinterpret_cast(GetKeyboardLayout(0)), - SORT_DEFAULT - ); - keyboardInputLocale = qt_localeFromLCID(newLCID); + bool bidi = false; -#ifdef UNICODE - if (QSysInfo::WindowsVersion >= QSysInfo::WV_2000) { - WCHAR wchLCIDFontSig[16]; - if (GetLocaleInfoW(newLCID, - LOCALE_FONTSIGNATURE, - &wchLCIDFontSig[0], - (sizeof(wchLCIDFontSig)/sizeof(WCHAR))) - && (wchLCIDFontSig[7] & (WCHAR)0x0800)) + wchar_t LCIDFontSig[16]; + if (GetLocaleInfo(newLCID, LOCALE_FONTSIGNATURE, LCIDFontSig, sizeof(LCIDFontSig) / sizeof(wchar_t)) + && (LCIDFontSig[7] & (wchar_t)0x0800)) bidi = true; - } else -#endif //UNICODE - { - if (newLCID == 0x0859 || //Sindhi (Arabic script) - newLCID == 0x0460) //Kashmiri (Arabic script) - bidi = true;; - - switch (PRIMARYLANGID(newLCID)) - { - case LANG_ARABIC: - case LANG_HEBREW: - case LANG_URDU: - case LANG_FARSI: - case LANG_PASHTO: - //case LANG_UIGHUR: - case LANG_SYRIAC: - case LANG_DIVEHI: - bidi = true; - } - } keyboardInputDirection = bidi ? Qt::RightToLeft : Qt::LeftToRight; } @@ -760,7 +693,7 @@ void QKeyMapperPrivate::updatePossibleKeyCodes(unsigned char *kbdBuffer, quint32 keyLayout[vk_key]->qtKey[8] = fallbackKey; // If this vk_key a Dead Key - if (MapVirtualKey(vk_key, 2) & 0x80008000) { // (High-order dead key on Win 95 is 0x8000) + if (MapVirtualKey(vk_key, 2) & 0x80000000) { // Push a Space, then the original key through the low-level ToAscii functions. // We do this because these functions (ToAscii / ToUnicode) will alter the internal state of // the keyboard driver By doing the following, we set the keyboard driver state back to what @@ -837,13 +770,13 @@ bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, const MSG &msg, bool bool isNumpad = (msg.wParam >= VK_NUMPAD0 && msg.wParam <= VK_NUMPAD9); quint32 nModifiers = 0; - if (QSysInfo::WindowsVersion < QSysInfo::WV_NT || QSysInfo::WindowsVersion & QSysInfo::WV_CE_based) { +#if defined(QT_OS_WINCE) nModifiers |= (GetKeyState(VK_SHIFT ) < 0 ? ShiftAny : 0); nModifiers |= (GetKeyState(VK_CONTROL) < 0 ? ControlAny : 0); nModifiers |= (GetKeyState(VK_MENU ) < 0 ? AltAny : 0); nModifiers |= (GetKeyState(VK_LWIN ) < 0 ? MetaLeft : 0); nModifiers |= (GetKeyState(VK_RWIN ) < 0 ? MetaRight : 0); - } else { +#else // Map native modifiers to some bit representation nModifiers |= (GetKeyState(VK_LSHIFT ) & 0x80 ? ShiftLeft : 0); nModifiers |= (GetKeyState(VK_RSHIFT ) & 0x80 ? ShiftRight : 0); @@ -857,7 +790,8 @@ bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, const MSG &msg, bool nModifiers |= (GetKeyState(VK_CAPITAL ) & 0x01 ? CapsLock : 0); nModifiers |= (GetKeyState(VK_NUMLOCK ) & 0x01 ? NumLock : 0); nModifiers |= (GetKeyState(VK_SCROLL ) & 0x01 ? ScrollLock : 0); - } +#endif // QT_OS_WINCE + if (msg.lParam & ExtendedKey) nModifiers |= msg.lParam & ExtendedKey; @@ -870,12 +804,12 @@ bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, const MSG &msg, bool // Now we know enough to either have MapVirtualKey or our own keymap tell us if it's a deadkey bool isDeadKey = isADeadKey(msg.wParam, state) - || MapVirtualKey(msg.wParam, 2) & 0x80008000; // High-order on 95 is 0x8000 + || MapVirtualKey(msg.wParam, 2) & 0x80000000; // A multi-character key not found by our look-ahead if (msgType == WM_CHAR) { QString s; - QChar ch = wmchar_to_unicode(msg.wParam); + QChar ch = QChar((ushort)msg.wParam); if (!ch.isNull()) s += ch; @@ -886,7 +820,7 @@ bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, const MSG &msg, bool // Input method characters not found by our look-ahead else if (msgType == WM_IME_CHAR) { QString s; - QChar ch = imechar_to_unicode(msg.wParam); + QChar ch = QChar((ushort)msg.wParam); if (!ch.isNull()) s += ch; @@ -1050,11 +984,9 @@ bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, const MSG &msg, bool : msgType == WM_IME_KEYDOWN ? WM_IME_CHAR : WM_SYSCHAR); QChar uch; - if (winPeekMessage(&wm_char, 0, charType, charType, PM_REMOVE)) { + if (PeekMessage(&wm_char, 0, charType, charType, PM_REMOVE)) { // Found a ?_CHAR - uch = charType == WM_IME_CHAR - ? imechar_to_unicode(wm_char.wParam) - : wmchar_to_unicode(wm_char.wParam); + uch = QChar((ushort)wm_char.wParam); if (msgType == WM_SYSKEYDOWN && uch.isLetter() && (msg.lParam & KF_ALTDOWN)) uch = uch.toLower(); // (See doc of WM_SYSCHAR) Alt-letter if (!code && !uch.row()) @@ -1067,7 +999,7 @@ bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, const MSG &msg, bool // to find the correct key using the current message parameters & keyboard state. if (uch.isNull() && msgType == WM_IME_KEYDOWN) { BYTE keyState[256]; - WCHAR newKey[3] = {0}; + wchar_t newKey[3] = {0}; GetKeyboardState(keyState); int val = ToUnicode(vk_key, scancode, keyState, newKey, 2, 0); if (val == 1) { @@ -1085,18 +1017,10 @@ bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, const MSG &msg, bool uch = QChar(QLatin1Char(0x7f)); // Windows doesn't know this one. } else { if (msgType != WM_SYSKEYDOWN || !code) { - UINT map; - QT_WA({ - map = MapVirtualKey(msg.wParam, 2); - } , { - map = MapVirtualKeyA(msg.wParam, 2); - // High-order bit is 0x8000 on '95 - if (map & 0x8000) - map = (map^0x8000)|0x80000000; - }); + UINT map = MapVirtualKey(msg.wParam, 2); // If the high bit of the return value is set, it's a deadkey if (!(map & 0x80000000)) - uch = wmchar_to_unicode((DWORD)map); + uch = QChar((ushort)map); } } if (!code && !uch.row()) @@ -1237,6 +1161,8 @@ bool QKeyMapper::sendKeyEvent(QWidget *widget, bool grab, if (QApplicationPrivate::instance()->qt_tryAccelEvent(widget, &a)) return true; } +#else + Q_UNUSED(grab); #endif if (!widget->isEnabled()) return false; diff --git a/src/gui/kernel/qmime_win.cpp b/src/gui/kernel/qmime_win.cpp index bc15638..c7559d8 100644 --- a/src/gui/kernel/qmime_win.cpp +++ b/src/gui/kernel/qmime_win.cpp @@ -281,11 +281,7 @@ QWindowsMime::~QWindowsMime() */ int QWindowsMime::registerMimeType(const QString &mime) { -#ifdef Q_OS_WINCE int f = RegisterClipboardFormat(reinterpret_cast (mime.utf16())); -#else - int f = RegisterClipboardFormatA(mime.toLocal8Bit()); -#endif if (!f) qErrnoWarning("QWindowsMime::registerMimeType: Failed to register clipboard format"); @@ -401,9 +397,9 @@ QStringList QWindowsMime::allMimesForFormats(IDataObject *pDataObj) while (S_OK == fmtenum->Next(1, &fmtetc, 0)) { #if defined(QMIME_DEBUG) && !defined(Q_OS_WINCE) qDebug("QWindowsMime::allMimesForFormats()"); - char buf[256] = {0}; - GetClipboardFormatNameA(fmtetc.cfFormat, buf, 255); - qDebug("CF = %d : %s", fmtetc.cfFormat, buf); + wchar_t buf[256] = {0}; + GetClipboardFormatName(fmtetc.cfFormat, buf, 255); + qDebug("CF = %d : %s", fmtetc.cfFormat, QString::fromWCharArray(buf)); #endif for (int i=mimes.size()-1; i>=0; --i) { QString format = mimes.at(i)->mimeForFormat(fmtetc); @@ -504,7 +500,7 @@ bool QWindowsMimeText::convertFromMime(const FORMATETC &formatetc, const QMimeDa ++u; } res.truncate(ri); - const int byteLength = res.length()*2; + const int byteLength = res.length() * sizeof(ushort); QByteArray r(byteLength + 2, '\0'); memcpy(r.data(), res.unicode(), byteLength); r[byteLength] = 0; @@ -549,7 +545,7 @@ QVariant QWindowsMimeText::convertToMime(const QString &mime, LPDATAOBJECT pData QString str; QByteArray data = getData(CF_UNICODETEXT, pDataObj); if (!data.isEmpty()) { - str = QString::fromUtf16((const unsigned short *)data.data()); + str = QString::fromWCharArray((const wchar_t *)data.data()); str.replace(QLatin1String("\r\n"), QLatin1String("\n")); } else { data = getData(CF_TEXT, pDataObj); @@ -620,11 +616,7 @@ bool QWindowsMimeURI::convertFromMime(const FORMATETC &formatetc, const QMimeDat for (int i=0; ifNC = true; char* files = ((char*)d) + d->pFiles; - QT_WA({ - d->fWide = true; - TCHAR* f = (TCHAR*)files; - for (int i=0; ifWide = false; - char* f = files; - for (int i=0; ifWide = true; + wchar_t* f = (wchar_t*)files; + for (int i=0; i urls = mimeData->urls(); QByteArray result; QString url = urls.at(0).toString(); - result = QByteArray((const char *)url.utf16(), url.length() * 2); + result = QByteArray((const char *)url.utf16(), url.length() * sizeof(ushort)); result.append('\0'); result.append('\0'); return setData(result, pmedium); @@ -720,15 +698,15 @@ QVariant QWindowsMimeURI::convertToMime(const QString &mimeType, LPDATAOBJECT pD LPDROPFILES hdrop = (LPDROPFILES)data.data(); if (hdrop->fWide) { - const ushort* filesw = (const ushort*)(data.data() + hdrop->pFiles); - int i=0; + const wchar_t* filesw = (const wchar_t *)(data.data() + hdrop->pFiles); + int i = 0; while (filesw[i]) { - QString fileurl = QString::fromUtf16(filesw+i); + QString fileurl = QString::fromWCharArray(filesw + i); urls += QUrl::fromLocalFile(fileurl); i += fileurl.length()+1; } } else { - const char* files = (const char*)data.data() + hdrop->pFiles; + const char* files = (const char *)data.data() + hdrop->pFiles; int i=0; while (files[i]) { urls += QUrl::fromLocalFile(QString::fromLocal8Bit(files+i)); @@ -744,7 +722,7 @@ QVariant QWindowsMimeURI::convertToMime(const QString &mimeType, LPDATAOBJECT pD QByteArray data = getData(CF_INETURL_W, pDataObj); if (data.isEmpty()) return QVariant(); - return QUrl(QString::fromUtf16((const unsigned short *)data.constData())); + return QUrl(QString::fromWCharArray((const wchar_t *)data.constData())); } else if (canGetData(CF_INETURL, pDataObj)) { QByteArray data = getData(CF_INETURL, pDataObj); if (data.isEmpty()) @@ -913,11 +891,7 @@ private: QWindowsMimeImage::QWindowsMimeImage() { -#ifdef Q_OS_WINCE - CF_PNG = RegisterClipboardFormat(reinterpret_cast (QString::fromLatin1("PNG").utf16())); -#else - CF_PNG = RegisterClipboardFormatA("PNG"); -#endif + CF_PNG = RegisterClipboardFormat(L"PNG"); } QVector QWindowsMimeImage::formatsForMime(const QString &mimeType, const QMimeData *mimeData) const @@ -1114,7 +1088,7 @@ bool QBuiltInMimes::convertFromMime(const FORMATETC &formatetc, const QMimeData ++u; } res.truncate(ri); - const int byteLength = res.length()*2; + const int byteLength = res.length() * sizeof(ushort); QByteArray r(byteLength + 2, '\0'); memcpy(r.data(), res.unicode(), byteLength); r[byteLength] = 0; @@ -1154,8 +1128,8 @@ QVariant QBuiltInMimes::convertToMime(const QString &mimeType, IDataObject *pDat qDebug("QBuiltInMimes::convertToMime()"); #endif if (mimeType == QLatin1String("text/html") && preferredType == QVariant::String) { - // text/html is in wide chars on windows (compatible with mozillia) - val = QString::fromUtf16((const unsigned short *)data.data()); + // text/html is in wide chars on windows (compatible with Mozilla) + val = QString::fromWCharArray((const wchar_t *)data.data()); } else { val = data; // it should be enough to return the data and let QMimeData do the rest. } @@ -1280,11 +1254,7 @@ bool QLastResortMimes::canConvertToMime(const QString &mimeType, IDataObject *pD { if (isCustomMimeType(mimeType)) { QString clipFormat = customMimeType(mimeType); -#ifdef Q_OS_WINCE int cf = RegisterClipboardFormat(reinterpret_cast (clipFormat.utf16())); -#else - int cf = RegisterClipboardFormatA(clipFormat.toLocal8Bit()); -#endif return canGetData(cf, pDataObj); } else if (formats.keys(mimeType).isEmpty()) { // if it is not in there then register it an see if we can get it @@ -1304,11 +1274,7 @@ QVariant QLastResortMimes::convertToMime(const QString &mimeType, IDataObject *p QByteArray data; if (isCustomMimeType(mimeType)) { QString clipFormat = customMimeType(mimeType); -#ifdef Q_OS_WINCE int cf = RegisterClipboardFormat(reinterpret_cast (clipFormat.utf16())); -#else - int cf = RegisterClipboardFormatA(clipFormat.toLocal8Bit()); -#endif data = getData(cf, pDataObj); } else if (formats.keys(mimeType).isEmpty()) { int cf = QWindowsMime::registerMimeType(mimeType); @@ -1325,46 +1291,38 @@ QVariant QLastResortMimes::convertToMime(const QString &mimeType, IDataObject *p QString QLastResortMimes::mimeForFormat(const FORMATETC &formatetc) const { QString format = formats.value(getCf(formatetc)); - if (format.isEmpty()) { - QByteArray ba; - QString clipFormat; - int len; - QT_WA({ - ba.resize(256*2); - len = GetClipboardFormatNameW(getCf(formatetc), (TCHAR*)ba.data(), 255); - if (len) - clipFormat = QString::fromUtf16((ushort *)ba.data(), len); - } , { - ba.resize(256); - len = GetClipboardFormatNameA(getCf(formatetc), ba.data(), 255); - if (len) - clipFormat = QString::fromLocal8Bit(ba.data(), len); - }); - if (len) { + if (!format.isEmpty()) + return format; + + wchar_t buffer[256]; + int len = GetClipboardFormatName(getCf(formatetc), buffer, 256); + + if (len) { + QString clipFormat = QString::fromWCharArray(buffer, len); #ifndef QT_NO_DRAGANDDROP - if (QInternalMimeData::canReadData(clipFormat)) - format = clipFormat; - else if((formatetc.cfFormat >= 0xC000)){ - //create the mime as custom. not registered. - if (!excludeList.contains(clipFormat, Qt::CaseInsensitive)) { - //check if this is a mime type - bool ianaType = false; - int sz = ianaTypes.size(); - for (int i = 0; i < sz; i++) { - if (clipFormat.startsWith(ianaTypes[i], Qt::CaseInsensitive)) { - ianaType = true; - break; - } + if (QInternalMimeData::canReadData(clipFormat)) + format = clipFormat; + else if((formatetc.cfFormat >= 0xC000)){ + //create the mime as custom. not registered. + if (!excludeList.contains(clipFormat, Qt::CaseInsensitive)) { + //check if this is a mime type + bool ianaType = false; + int sz = ianaTypes.size(); + for (int i = 0; i < sz; i++) { + if (clipFormat.startsWith(ianaTypes[i], Qt::CaseInsensitive)) { + ianaType = true; + break; } - if (!ianaType) - format = QLatin1String(x_qt_windows_mime) + clipFormat + QLatin1Char('\"'); - else - format = clipFormat; } + if (!ianaType) + format = QLatin1String(x_qt_windows_mime) + clipFormat + QLatin1Char('\"'); + else + format = clipFormat; } -#endif //QT_NO_DRAGANDDROP } +#endif //QT_NO_DRAGANDDROP } + return format; } diff --git a/src/gui/kernel/qsound_win.cpp b/src/gui/kernel/qsound_win.cpp index 7330d4b..82854ae 100644 --- a/src/gui/kernel/qsound_win.cpp +++ b/src/gui/kernel/qsound_win.cpp @@ -77,13 +77,8 @@ public: QAuServerWindows::QAuServerWindows(QObject* parent) : QAuServer(parent), current(0) { - QT_WA({ - mutex = CreateMutexW(0, 0, 0); - event = CreateEventW(0, FALSE, FALSE, 0); - } , { - mutex = CreateMutexA(0, 0, 0); - event = CreateEventA(0, FALSE, FALSE, 0); - }); + mutex = CreateMutex(0, 0, 0); + event = CreateEvent(0, FALSE, FALSE, 0); } QAuServerWindows::~QAuServerWindows() @@ -133,13 +128,9 @@ DWORD WINAPI SoundPlayProc(LPVOID param) if (loops == -1) flags |= SND_LOOP; - QT_WA({ - PlaySoundW((TCHAR*)filename.utf16(), 0, flags); - } , { - PlaySoundA(QFile::encodeName(filename).data(), 0, flags); - }); - if (sound && loops == 1) - server->decLoop(sound); + PlaySound((wchar_t*)filename.utf16(), 0, flags); + if (sound && loops == 1) + server->decLoop(sound); // GUI thread continues, but we are done as well. SetEvent(event); @@ -148,18 +139,13 @@ DWORD WINAPI SoundPlayProc(LPVOID param) QPointer guarded_sound = sound; SetEvent(event); - for (int l = 0; l < loops && server->current; ++l) { - QT_WA( { - PlaySoundW( (TCHAR*)filename.utf16(), 0, SND_FILENAME|SND_SYNC ); - } , { - PlaySoundA( QFile::encodeName(filename).data(), 0, - SND_FILENAME|SND_SYNC ); - } ); - - if (guarded_sound) - server->decLoop(guarded_sound); - } - server->current = 0; + for (int l = 0; l < loops && server->current; ++l) { + PlaySound((wchar_t*)filename.utf16(), 0, SND_FILENAME | SND_SYNC); + + if (guarded_sound) + server->decLoop(guarded_sound); + } + server->current = 0; } ReleaseMutex(mutex); @@ -169,7 +155,7 @@ DWORD WINAPI SoundPlayProc(LPVOID param) void QAuServerWindows::playHelper(const QString &filename, int loop, QSound *snd) { if (loop == 0) - return; + return; // busy? if (WaitForSingleObject(mutex, 0) == WAIT_TIMEOUT) return; diff --git a/src/gui/kernel/qwhatsthis.cpp b/src/gui/kernel/qwhatsthis.cpp index 067c783..f38b0f6 100644 --- a/src/gui/kernel/qwhatsthis.cpp +++ b/src/gui/kernel/qwhatsthis.cpp @@ -226,7 +226,9 @@ QWhatsThat::QWhatsThat(const QString& txt, QWidget* parent, QWidget *showTextFor text); } #if defined(Q_WS_WIN) - if ((QSysInfo::WindowsVersion&QSysInfo::WV_NT_based) > QSysInfo::WV_2000) { + if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP + && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)) + { BOOL shadow; SystemParametersInfo(SPI_GETDROPSHADOW, 0, &shadow, 0); shadowWidth = shadow ? 0 : 6; @@ -302,7 +304,9 @@ void QWhatsThat::paintEvent(QPaintEvent*) { bool drawShadow = true; #if defined(Q_WS_WIN) - if ((QSysInfo::WindowsVersion&QSysInfo::WV_NT_based) > QSysInfo::WV_2000) { + if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP + && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based)) + { BOOL shadow; SystemParametersInfo(SPI_GETDROPSHADOW, 0, &shadow, 0); drawShadow = !shadow; diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 304d72a..1b31318 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -863,8 +863,8 @@ void QWidget::setAutoFillBackground(bool enabled) \list \o X11: This feature relies on the use of an X server that supports ARGB visuals and a compositing window manager. - \o Windows: This feature requires Windows 2000 or later. The widget needs to have - the Qt::FramelessWindowHint window flag set for the translucency to work. + \o Windows: The widget needs to have the Qt::FramelessWindowHint window flag set + for the translucency to work. \endlist @@ -9964,8 +9964,8 @@ bool QWidget::testAttribute_helper(Qt::WidgetAttribute attribute) const By default the value of this property is 1.0. - This feature is available on Embedded Linux, Mac OS X, X11 platforms that - support the Composite extension, and Windows 2000 and later. + This feature is available on Embedded Linux, Mac OS X, Windows, + and X11 platforms that support the Composite extension. This feature is not available on Windows CE. diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp index e39ca77..dcf541c 100644 --- a/src/gui/kernel/qwidget_win.cpp +++ b/src/gui/kernel/qwidget_win.cpp @@ -140,14 +140,8 @@ static void init_wintab_functions() if (!qt_is_gui_used) return; QLibrary library(QLatin1String("wintab32")); - QT_WA({ - ptrWTOpen = (PtrWTOpen)library.resolve("WTOpenW"); - ptrWTInfo = (PtrWTInfo)library.resolve("WTInfoW"); - } , { - ptrWTOpen = (PtrWTOpen)library.resolve("WTOpenA"); - ptrWTInfo = (PtrWTInfo)library.resolve("WTInfoA"); - }); - + ptrWTOpen = (PtrWTOpen)library.resolve("WTOpenW"); + ptrWTInfo = (PtrWTInfo)library.resolve("WTInfoW"); ptrWTClose = (PtrWTClose)library.resolve("WTClose"); ptrWTQueueSizeGet = (PtrWTQueueSizeGet)library.resolve("WTQueueSizeGet"); ptrWTQueueSizeSet = (PtrWTQueueSizeSet)library.resolve("WTQueueSizeSet"); @@ -287,25 +281,18 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO if (desktop && !q->testAttribute(Qt::WA_DontShowOnScreen)) { // desktop widget popup = false; // force this flags off - if (QSysInfo::WindowsVersion != QSysInfo::WV_NT && QSysInfo::WindowsVersion != QSysInfo::WV_95) - data.crect.setRect(GetSystemMetrics(76 /* SM_XVIRTUALSCREEN */), GetSystemMetrics(77 /* SM_YVIRTUALSCREEN */), + data.crect.setRect(GetSystemMetrics(76 /* SM_XVIRTUALSCREEN */), GetSystemMetrics(77 /* SM_YVIRTUALSCREEN */), GetSystemMetrics(78 /* SM_CXVIRTUALSCREEN */), GetSystemMetrics(79 /* SM_CYVIRTUALSCREEN */)); - else - data.crect.setRect(0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); } parentw = q->parentWidget() ? q->parentWidget()->effectiveWinId() : 0; -#ifdef UNICODE QString title; - const TCHAR *ttitle = 0; -#endif - QByteArray title95; int style = WS_CHILD; int exsty = 0; if (window) { - style = GetWindowLongA(window, GWL_STYLE); + style = GetWindowLong(window, GWL_STYLE); if (!style) qErrnoWarning("QWidget::create: GetWindowLong failed"); topLevel = false; // #### needed for some IE plugins?? @@ -361,12 +348,7 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO } if (flags & Qt::WindowTitleHint) { - QT_WA({ - title = q->isWindow() ? qAppName() : q->objectName(); - ttitle = (TCHAR*)title.utf16(); - } , { - title95 = q->isWindow() ? qAppName().toLocal8Bit() : q->objectName().toLatin1(); - }); + title = q->isWindow() ? qAppName() : q->objectName(); } // The Qt::WA_WState_Created flag is checked by translateConfigEvent() in @@ -379,13 +361,13 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO destroyw = data.winid; id = window; setWinId(window); - LONG res = SetWindowLongA(window, GWL_STYLE, style); + LONG res = SetWindowLong(window, GWL_STYLE, style); if (!res) qErrnoWarning("QWidget::create: Failed to set window style"); #ifdef _WIN64 - res = SetWindowLongPtrA( window, GWLP_WNDPROC, (LONG_PTR)QtWndProc ); + res = SetWindowLongPtr( window, GWLP_WNDPROC, (LONG_PTR)QtWndProc ); #else - res = SetWindowLongA( window, GWL_WNDPROC, (LONG)QtWndProc ); + res = SetWindowLong( window, GWL_WNDPROC, (LONG)QtWndProc ); #endif if (!res) qErrnoWarning("QWidget::create: Failed to set window procedure"); @@ -436,16 +418,10 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO } } - QT_WA({ - const TCHAR *cname = (TCHAR*)windowClassName.utf16(); - id = CreateWindowEx(exsty, cname, ttitle, style, - x, y, w, h, - parentw, 0, appinst, 0); - } , { - id = CreateWindowExA(exsty, windowClassName.toLatin1(), title95, style, - x, y, w, h, - parentw, 0, appinst, 0); - }); + id = CreateWindowEx(exsty, reinterpret_cast(windowClassName.utf16()), + reinterpret_cast(title.utf16()), style, + x, y, w, h, + parentw, NULL, appinst, NULL); if (!id) qErrnoWarning("QWidget::create: Failed to create window"); setWinId(id); @@ -457,16 +433,10 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO SetWindowPos(id, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); winUpdateIsOpaque(); } else if (q->testAttribute(Qt::WA_NativeWindow) || paintOnScreen()) { // create child widget - QT_WA({ - const TCHAR *cname = (TCHAR*)windowClassName.utf16(); - id = CreateWindowEx(exsty, cname, ttitle, style, - data.crect.left(), data.crect.top(), data.crect.width(), data.crect.height(), - parentw, NULL, appinst, NULL); - } , { - id = CreateWindowExA(exsty, windowClassName.toLatin1(), title95, style, - data.crect.left(), data.crect.top(), data.crect.width(), data.crect.height(), + id = CreateWindowEx(exsty, reinterpret_cast(windowClassName.utf16()), + reinterpret_cast(title.utf16()), style, + data.crect.left(), data.crect.top(), data.crect.width(), data.crect.height(), parentw, NULL, appinst, NULL); - }); if (!id) qErrnoWarning("QWidget::create: Failed to create window"); SetWindowPos(id, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); @@ -682,7 +652,7 @@ void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f) // Show borderless toplevel windows in tasklist & NavBar if (!parent) { QString txt = q->windowTitle().isEmpty()?qAppName():q->windowTitle(); - SetWindowText(q->internalWinId(), (TCHAR*)txt.utf16()); + SetWindowText(q->internalWinId(), (wchar_t*)txt.utf16()); } #endif invalidateBuffer(q->rect()); @@ -767,11 +737,7 @@ void QWidgetPrivate::setWindowTitle_sys(const QString &caption) return; Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); - QT_WA({ - SetWindowText(q->internalWinId(), (TCHAR*)caption.utf16()); - } , { - SetWindowTextA(q->internalWinId(), caption.toLocal8Bit()); - }); + SetWindowText(q->internalWinId(), (wchar_t*)caption.utf16()); } /* @@ -853,11 +819,11 @@ void QWidgetPrivate::setWindowIcon_sys(bool forceReset) GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), &(x->iconPixmap)); if (x->winIconBig) { - SendMessageA(q->internalWinId(), WM_SETICON, 0 /* ICON_SMALL */, (LPARAM)x->winIconSmall); - SendMessageA(q->internalWinId(), WM_SETICON, 1 /* ICON_BIG */, (LPARAM)x->winIconBig); + SendMessage(q->internalWinId(), WM_SETICON, 0 /* ICON_SMALL */, (LPARAM)x->winIconSmall); + SendMessage(q->internalWinId(), WM_SETICON, 1 /* ICON_BIG */, (LPARAM)x->winIconBig); } else { - SendMessageA(q->internalWinId(), WM_SETICON, 0 /* ICON_SMALL */, (LPARAM)x->winIconSmall); - SendMessageA(q->internalWinId(), WM_SETICON, 1 /* ICON_BIG */, (LPARAM)x->winIconSmall); + SendMessage(q->internalWinId(), WM_SETICON, 0 /* ICON_SMALL */, (LPARAM)x->winIconSmall); + SendMessage(q->internalWinId(), WM_SETICON, 1 /* ICON_BIG */, (LPARAM)x->winIconSmall); } } @@ -884,7 +850,7 @@ LRESULT CALLBACK qJournalRecordProc(int nCode, WPARAM wParam, LPARAM lParam) /* Works only as long as pointer is inside the application's window, which is good enough for QDockWidget. - Doesn't call SetWindowsHookExA() - this function causes a system-wide + Doesn't call SetWindowsHookEx() - this function causes a system-wide freeze if any other app on the system installs a hook and fails to process events. */ void QWidgetPrivate::grabMouseWhileInWindow() @@ -908,7 +874,7 @@ void QWidget::grabMouse() if (!qt_nograb()) { if (mouseGrb) mouseGrb->releaseMouse(); - journalRec = SetWindowsHookExA(WH_JOURNALRECORD, (HOOKPROC)qJournalRecordProc, GetModuleHandleA(0), 0); + journalRec = SetWindowsHookEx(WH_JOURNALRECORD, (HOOKPROC)qJournalRecordProc, GetModuleHandle(0), 0); Q_ASSERT(testAttribute(Qt::WA_WState_Created)); SetCapture(effectiveWinId()); mouseGrb = this; @@ -921,7 +887,7 @@ void QWidget::grabMouse(const QCursor &cursor) if (!qt_nograb()) { if (mouseGrb) mouseGrb->releaseMouse(); - journalRec = SetWindowsHookExA(WH_JOURNALRECORD, (HOOKPROC)qJournalRecordProc, GetModuleHandleA(0), 0); + journalRec = SetWindowsHookEx(WH_JOURNALRECORD, (HOOKPROC)qJournalRecordProc, GetModuleHandle(0), 0); Q_ASSERT(testAttribute(Qt::WA_WState_Created)); SetCapture(effectiveWinId()); mouseGrbCur = new QCursor(cursor); @@ -1028,7 +994,7 @@ void QWidget::setWindowState(Qt::WindowStates newstate) if (newstate & Qt::WindowFullScreen) { if (d->topData()->normalGeometry.width() < 0 && !(oldstate & Qt::WindowMaximized)) d->topData()->normalGeometry = geometry(); - d->topData()->savedFlags = Qt::WindowFlags(GetWindowLongA(internalWinId(), GWL_STYLE)); + d->topData()->savedFlags = Qt::WindowFlags(GetWindowLong(internalWinId(), GWL_STYLE)); #ifndef Q_FLATTEN_EXPOSE UINT style = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_POPUP; #else @@ -1038,7 +1004,7 @@ void QWidget::setWindowState(Qt::WindowStates newstate) style |= WS_SYSMENU; if (isVisible()) style |= WS_VISIBLE; - SetWindowLongA(internalWinId(), GWL_STYLE, style); + SetWindowLong(internalWinId(), GWL_STYLE, style); QRect r = QApplication::desktop()->screenGeometry(this); UINT swpf = SWP_FRAMECHANGED; if (newstate & Qt::WindowActive) @@ -1050,7 +1016,7 @@ void QWidget::setWindowState(Qt::WindowStates newstate) UINT style = d->topData()->savedFlags; if (isVisible()) style |= WS_VISIBLE; - SetWindowLongA(internalWinId(), GWL_STYLE, style); + SetWindowLong(internalWinId(), GWL_STYLE, style); UINT swpf = SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE; if (newstate & Qt::WindowActive) @@ -1395,7 +1361,7 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) UINT style = top->savedFlags; if (q->isVisible()) style |= WS_VISIBLE; - SetWindowLongA(q->internalWinId(), GWL_STYLE, style); + SetWindowLong(q->internalWinId(), GWL_STYLE, style); UINT swpf = SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE; if (data.window_state & Qt::WindowActive) @@ -1410,7 +1376,7 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData(); const bool inTopLevelResize = tlwExtra ? tlwExtra->inTopLevelResize : false; const bool isTranslucentWindow = !isOpaque && ptrUpdateLayeredWindowIndirect && (data.window_flags & Qt::FramelessWindowHint) - && GetWindowLongA(q->internalWinId(), GWL_EXSTYLE) & Q_WS_EX_LAYERED; + && GetWindowLong(q->internalWinId(), GWL_EXSTYLE) & Q_WS_EX_LAYERED; if (q->testAttribute(Qt::WA_WState_ConfigPending)) { // processing config event if (q->internalWinId()) @@ -1578,11 +1544,11 @@ void QWidgetPrivate::winUpdateIsOpaque() return; if (!isOpaque && ptrUpdateLayeredWindowIndirect) { - SetWindowLongA(q->internalWinId(), GWL_EXSTYLE, - GetWindowLongA(q->internalWinId(), GWL_EXSTYLE) | Q_WS_EX_LAYERED); + SetWindowLong(q->internalWinId(), GWL_EXSTYLE, + GetWindowLong(q->internalWinId(), GWL_EXSTYLE) | Q_WS_EX_LAYERED); } else { - SetWindowLongA(q->internalWinId(), GWL_EXSTYLE, - GetWindowLongA(q->internalWinId(), GWL_EXSTYLE) & ~Q_WS_EX_LAYERED); + SetWindowLong(q->internalWinId(), GWL_EXSTYLE, + GetWindowLong(q->internalWinId(), GWL_EXSTYLE) & ~Q_WS_EX_LAYERED); } #endif } @@ -1592,12 +1558,12 @@ void QWidgetPrivate::setConstraints_sys() #ifndef Q_WS_WINCE_WM Q_Q(QWidget); if (q->isWindow() && q->testAttribute(Qt::WA_WState_Created)) { - int style = GetWindowLongA(q->internalWinId(), GWL_STYLE); + int style = GetWindowLong(q->internalWinId(), GWL_STYLE); if (shouldShowMaximizeButton()) style |= WS_MAXIMIZEBOX; else style &= ~WS_MAXIMIZEBOX; - SetWindowLongA(q->internalWinId(), GWL_STYLE, style); + SetWindowLong(q->internalWinId(), GWL_STYLE, style); } #endif } @@ -1867,10 +1833,8 @@ void QWidgetPrivate::updateFrameStrut() RECT rect = {0,0,0,0}; QTLWExtra *top = topData(); - uint exstyle = QT_WA_INLINE(GetWindowLongW(q->internalWinId(), GWL_EXSTYLE), - GetWindowLongA(q->internalWinId(), GWL_EXSTYLE)); - uint style = QT_WA_INLINE(GetWindowLongW(q->internalWinId(), GWL_STYLE), - GetWindowLongA(q->internalWinId(), GWL_STYLE)); + uint exstyle = GetWindowLong(q->internalWinId(), GWL_EXSTYLE); + uint style = GetWindowLong(q->internalWinId(), GWL_STYLE); #ifndef Q_WS_WINCE if (AdjustWindowRectEx(&rect, style & ~(WS_OVERLAPPED), FALSE, exstyle)) { #else @@ -1886,11 +1850,10 @@ void QWidgetPrivate::setWindowOpacity_sys(qreal level) { Q_Q(QWidget); - if (!isOpaque && ptrUpdateLayeredWindowIndirect && (data.window_flags & Qt::FramelessWindowHint)) { - if (GetWindowLongA(q->internalWinId(), GWL_EXSTYLE) & Q_WS_EX_LAYERED) { - Q_BLENDFUNCTION blend = {AC_SRC_OVER, 0, (int)(255.0 * level), Q_AC_SRC_ALPHA}; - Q_UPDATELAYEREDWINDOWINFO info = {sizeof(info), NULL, NULL, NULL, NULL, NULL, 0, &blend, Q_ULW_ALPHA, NULL}; - (*ptrUpdateLayeredWindowIndirect)(q->internalWinId(), &info); + if (!isOpaque && ptrUpdateLayeredWindow && (data.window_flags & Qt::FramelessWindowHint)) { + if (GetWindowLong(q->internalWinId(), GWL_EXSTYLE) & Q_WS_EX_LAYERED) { + BLENDFUNCTION blend = {AC_SRC_OVER, 0, (int)(255.0 * level), AC_SRC_ALPHA}; + ptrUpdateLayeredWindow(q->internalWinId(), NULL, NULL, NULL, NULL, NULL, 0, &blend, Q_ULW_ALPHA); } return; } @@ -1906,15 +1869,15 @@ void QWidgetPrivate::setWindowOpacity_sys(qreal level) if (!ptrSetLayeredWindowAttributes) return; - int wl = GetWindowLongA(q->internalWinId(), GWL_EXSTYLE); + int wl = GetWindowLong(q->internalWinId(), GWL_EXSTYLE); if (level != 1.0) { if ((wl&Q_WS_EX_LAYERED) == 0) - SetWindowLongA(q->internalWinId(), GWL_EXSTYLE, wl|Q_WS_EX_LAYERED); + SetWindowLong(q->internalWinId(), GWL_EXSTYLE, wl | Q_WS_EX_LAYERED); } else if (wl&Q_WS_EX_LAYERED) { - SetWindowLongA(q->internalWinId(), GWL_EXSTYLE, wl & ~Q_WS_EX_LAYERED); + SetWindowLong(q->internalWinId(), GWL_EXSTYLE, wl & ~Q_WS_EX_LAYERED); } - (*ptrSetLayeredWindowAttributes)(q->internalWinId(), 0, (int)(level * 255), Q_LWA_ALPHA); + ptrSetLayeredWindowAttributes(q->internalWinId(), 0, (int)(level * 255), Q_LWA_ALPHA); } #endif //Q_WS_WINCE diff --git a/src/gui/kernel/qwidget_wince.cpp b/src/gui/kernel/qwidget_wince.cpp index 24d8156..b0eaa12 100644 --- a/src/gui/kernel/qwidget_wince.cpp +++ b/src/gui/kernel/qwidget_wince.cpp @@ -188,11 +188,7 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO parentw = q->parentWidget() ? q->parentWidget()->effectiveWinId() : 0; -#ifdef UNICODE QString title; - const TCHAR *ttitle = 0; -#endif - QByteArray title95; int style = WS_CHILD; int exsty = WS_EX_NOPARENTNOTIFY; @@ -236,12 +232,7 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO } if (flags & Qt::WindowTitleHint) { - QT_WA({ - title = q->isWindow() ? qAppName() : q->objectName(); - ttitle = (TCHAR*)title.utf16(); - } , { - title95 = q->isWindow() ? qAppName().toLocal8Bit() : q->objectName().toLatin1(); - }); + title = q->isWindow() ? qAppName() : q->objectName(); } // The Qt::WA_WState_Created flag is checked by translateConfigEvent() in @@ -254,11 +245,11 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO destroyw = data.winid; id = window; setWinId(window); - LONG res = SetWindowLongA(window, GWL_STYLE, style); + LONG res = SetWindowLong(window, GWL_STYLE, style); if (!res) qErrnoWarning("QWidget::create: Failed to set window style"); - res = SetWindowLongA( window, GWL_WNDPROC, (LONG)QtWndProc ); + res = SetWindowLong( window, GWL_WNDPROC, (LONG)QtWndProc ); if (!res) qErrnoWarning("QWidget::create: Failed to set window procedure"); @@ -267,10 +258,10 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO if (!id) { //Create a dummy desktop RECT r; SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0); - const TCHAR *cname = reinterpret_cast (windowClassName.utf16()); - id = CreateWindow(cname, ttitle, style, - r.left, r.top, r.right - r.left, r.bottom - r.top, - 0, 0, appinst, 0); + id = CreateWindow(reinterpret_cast(windowClassName.utf16()), + reinterpret_cast(title.utf16()), style, + r.left, r.top, r.right - r.left, r.bottom - r.top, + 0, 0, appinst, 0); } setWinId(id); } else if (topLevel) { // create top-level widget @@ -303,8 +294,8 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO } } - const TCHAR *cname = reinterpret_cast (windowClassName.utf16()); - id = CreateWindowEx(exsty, cname, ttitle, style, + id = CreateWindowEx(exsty, reinterpret_cast(windowClassName.utf16()), + reinterpret_cast(title.utf16()), style, x, y, w, h, 0, 0, appinst, 0); @@ -314,16 +305,9 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO if ((flags & Qt::WindowStaysOnTopHint) || (type == Qt::ToolTip)) SetWindowPos(id, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); } else if (q->testAttribute(Qt::WA_NativeWindow) || paintOnScreen()) { // create child widget - QT_WA({ - const TCHAR *cname = (TCHAR*)windowClassName.utf16(); - id = CreateWindowEx(exsty, cname, ttitle, style, - data.crect.left(), data.crect.top(), data.crect.width(), data.crect.height(), - parentw, NULL, appinst, NULL); - } , { - id = CreateWindowExA(exsty, windowClassName.toLatin1(), title95, style, - data.crect.left(), data.crect.top(), data.crect.width(), data.crect.height(), + id = CreateWindowEx(exsty, (wchar_t*)windowClassName.utf16(), (wchar_t*)title.utf16(), style, + data.crect.left(), data.crect.top(), data.crect.width(), data.crect.height(), parentw, NULL, appinst, NULL); - }); if (!id) qErrnoWarning("QWidget::create: Failed to create window"); SetWindowPos(id, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); @@ -510,7 +494,7 @@ void QWidget::setWindowState(Qt::WindowStates newstate) } if ((oldstate & Qt::WindowMaximized) != (newstate & Qt::WindowMaximized)) { if (!(newstate & Qt::WindowMaximized)) { - int style = GetWindowLongW(internalWinId(), GWL_STYLE) | WS_BORDER | WS_POPUP | WS_CAPTION; + int style = GetWindowLong(internalWinId(), GWL_STYLE) | WS_BORDER | WS_POPUP | WS_CAPTION; SetWindowLong(internalWinId(), GWL_STYLE, style); SetWindowLong(internalWinId(), GWL_EXSTYLE, GetWindowLong (internalWinId(), GWL_EXSTYLE) & ~ WS_EX_NODRAG); } @@ -535,11 +519,11 @@ void QWidget::setWindowState(Qt::WindowStates newstate) if (newstate & Qt::WindowFullScreen) { if (d->topData()->normalGeometry.width() < 0 && !(oldstate & Qt::WindowMaximized)) d->topData()->normalGeometry = geometry(); - d->topData()->savedFlags = (Qt::WindowFlags) GetWindowLongA(internalWinId(), GWL_STYLE); + d->topData()->savedFlags = (Qt::WindowFlags)GetWindowLong(internalWinId(), GWL_STYLE); UINT style = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_POPUP; if (isVisible()) style |= WS_VISIBLE; - SetWindowLongA(internalWinId(), GWL_STYLE, style); + SetWindowLong(internalWinId(), GWL_STYLE, style); QRect r = qApp->desktop()->screenGeometry(this); UINT swpf = SWP_FRAMECHANGED; if (newstate & Qt::WindowActive) @@ -550,7 +534,7 @@ void QWidget::setWindowState(Qt::WindowStates newstate) UINT style = d->topData()->savedFlags; if (isVisible()) style |= WS_VISIBLE; - SetWindowLongA(internalWinId(), GWL_STYLE, style); + SetWindowLong(internalWinId(), GWL_STYLE, style); UINT swpf = SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE; if (newstate & Qt::WindowActive) swpf |= SWP_NOACTIVATE; diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp index 664751a..a6ecd4e 100644 --- a/src/gui/painting/qpdf.cpp +++ b/src/gui/painting/qpdf.cpp @@ -1923,7 +1923,7 @@ void QPdfBaseEnginePrivate::drawTextItem(const QPointF &p, const QTextItemInt &t #ifdef Q_WS_WIN if (ti.fontEngine->type() == QFontEngine::Win) { QFontEngineWin *fe = static_cast(ti.fontEngine); - size = fe->tm.w.tmHeight; + size = fe->tm.tmHeight; } #endif diff --git a/src/gui/painting/qprintengine_pdf.cpp b/src/gui/painting/qprintengine_pdf.cpp index c1edcb3..b267860 100644 --- a/src/gui/painting/qprintengine_pdf.cpp +++ b/src/gui/painting/qprintengine_pdf.cpp @@ -655,7 +655,7 @@ void QPdfEnginePrivate::drawTextItem(const QPointF &p, const QTextItemInt &ti) #ifdef Q_WS_WIN if (ti.fontEngine->type() == QFontEngine::Win) { QFontEngineWin *fe = static_cast(ti.fontEngine); - size = fe->tm.w.tmHeight; + size = fe->tm.tmHeight; } #endif int synthesized = ti.fontEngine->synthesized(); diff --git a/src/gui/painting/qprintengine_win.cpp b/src/gui/painting/qprintengine_win.cpp index f36028f..7b99e2f 100644 --- a/src/gui/painting/qprintengine_win.cpp +++ b/src/gui/painting/qprintengine_win.cpp @@ -199,33 +199,18 @@ bool QWin32PrintEngine::begin(QPaintDevice *pdev) if (d->printToFile && d->fileName.isEmpty()) d->fileName = d->port; - QT_WA({ - d->devModeW()->dmCopies = d->num_copies; - DOCINFO di; - memset(&di, 0, sizeof(DOCINFO)); - di.cbSize = sizeof(DOCINFO); - di.lpszDocName = reinterpret_cast(d->docName.utf16()); - if (d->printToFile && !d->fileName.isEmpty()) - di.lpszOutput = reinterpret_cast(d->fileName.utf16()); - if (ok && StartDoc(d->hdc, &di) == SP_ERROR) { - qErrnoWarning("QWin32PrintEngine::begin: StartDoc failed"); - ok = false; - } - } , { - d->devModeA()->dmCopies = d->num_copies; - DOCINFOA di; - memset(&di, 0, sizeof(DOCINFOA)); - di.cbSize = sizeof(DOCINFOA); - QByteArray docNameA = d->docName.toLocal8Bit(); - di.lpszDocName = docNameA.data(); - QByteArray outfileA = d->fileName.toLocal8Bit(); - if (d->printToFile && !d->fileName.isEmpty()) - di.lpszOutput = outfileA; - if (ok && StartDocA(d->hdc, &di) == SP_ERROR) { - qErrnoWarning("QWin32PrintEngine::begin: StartDoc failed"); - ok = false; - } - }); + d->devMode->dmCopies = d->num_copies; + + DOCINFO di; + memset(&di, 0, sizeof(DOCINFO)); + di.cbSize = sizeof(DOCINFO); + di.lpszDocName = reinterpret_cast(d->docName.utf16()); + if (d->printToFile && !d->fileName.isEmpty()) + di.lpszOutput = reinterpret_cast(d->fileName.utf16()); + if (ok && StartDoc(d->hdc, &di) == SP_ERROR) { + qErrnoWarning("QWin32PrintEngine::begin: StartDoc failed"); + ok = false; + } if (StartPage(d->hdc) <= 0) { qErrnoWarning("QWin32PrintEngine::begin: StartPage failed"); @@ -317,11 +302,6 @@ bool QWin32PrintEngine::newPage() bool success = false; if (d->hdc && d->state == QPrinter::Active) { -// bool restorePainter = false; -// if ((qWinVersion()& Qt::WV_DOS_based) && painter && painter->isActive()) { -// painter->save(); // EndPage/StartPage ruins the DC -// restorePainter = true; -// } if (EndPage(d->hdc) != SP_ERROR) { // reinitialize the DC before StartPage if needed, // because resetdc is disabled between calls to the StartPage and EndPage functions @@ -337,16 +317,10 @@ bool QWin32PrintEngine::newPage() } success = (StartPage(d->hdc) != SP_ERROR); } - if (!success) + if (!success) { d->state = QPrinter::Aborted; - -// if (qWinVersion() & Qt::WV_DOS_based) -// if (restorePainter) { -// painter->restore(); -// } - - if (!success) return false; + } } return true; } @@ -369,7 +343,7 @@ void QWin32PrintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem QRgb brushColor = state->pen().brush().color().rgb(); bool fallBack = state->pen().brush().style() != Qt::SolidPattern || qAlpha(brushColor) != 0xff - || QT_WA_INLINE(d->txop >= QTransform::TxProject, d->txop >= QTransform::TxScale) + || d->txop >= QTransform::TxProject || ti.fontEngine->type() != QFontEngine::Win; @@ -380,17 +354,10 @@ void QWin32PrintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem SelectObject(d->hdc, fe->hfont); if (GetDeviceCaps(d->hdc, TECHNOLOGY) != DT_CHARSTREAM) { - QT_WA({ - TCHAR n[64]; - GetTextFaceW(d->hdc, 64, n); - fallBack = QString::fromUtf16((ushort *)n) - != QString::fromUtf16((ushort *)fe->logfont.lfFaceName); - } , { - char an[64]; - GetTextFaceA(d->hdc, 64, an); - fallBack = QString::fromLocal8Bit(an) - != QString::fromLocal8Bit(((LOGFONTA*)(&fe->logfont))->lfFaceName); - }); + wchar_t n[64]; + GetTextFace(d->hdc, 64, n); + fallBack = QString::fromWCharArray(n) + != QString::fromWCharArray(fe->logfont.lfFaceName); } } @@ -983,22 +950,14 @@ void QWin32PrintEnginePrivate::queryDefault() * Strings "windows" and "device" are specified in the MSDN under EnumPrinters() */ QString noPrinters(QLatin1String("qt_no_printers")); - QString output; - QT_WA({ - ushort buffer[256]; - GetProfileStringW(L"windows", L"device", - reinterpret_cast(noPrinters.utf16()), - reinterpret_cast(buffer), 256); - output = QString::fromUtf16(buffer); - if (output.isEmpty() || output == noPrinters) // no printers - return; - }, { - char buffer[256]; - GetProfileStringA("windows", "device", noPrinters.toLatin1(), buffer, 256); - output = QString::fromLocal8Bit(buffer); - if (output.isEmpty() || output == noPrinters) // no printers - return; - }); + wchar_t buffer[256]; + GetProfileString(L"windows", L"device", + reinterpret_cast(noPrinters.utf16()), + buffer, 256); + QString output = QString::fromWCharArray(buffer); + if (output.isEmpty() || output == noPrinters) // no printers + return; + QStringList info = output.split(QLatin1Char(',')); if (info.size() > 0) { if (name.isEmpty()) @@ -1030,13 +989,7 @@ void QWin32PrintEnginePrivate::initialize() txop = QTransform::TxNone; - bool ok; - QT_WA( { - ok = OpenPrinterW((LPWSTR)name.utf16(), (LPHANDLE)&hPrinter, 0); - }, { - ok = OpenPrinterA((LPSTR)name.toLatin1().data(), (LPHANDLE)&hPrinter, 0); - } ); - + bool ok = OpenPrinter((LPWSTR)name.utf16(), (LPHANDLE)&hPrinter, 0); if (!ok) { qErrnoWarning("QWin32PrintEngine::initialize: OpenPrinter failed"); return; @@ -1045,22 +998,10 @@ void QWin32PrintEnginePrivate::initialize() // Fetch the PRINTER_INFO_2 with DEVMODE data containing the // printer settings. DWORD infoSize, numBytes; - ok = true; - QT_WA( { - GetPrinterW(hPrinter, 2, NULL, 0, &infoSize); - hMem = GlobalAlloc(GHND, infoSize); - pInfo = GlobalLock(hMem); - if (!GetPrinterW(hPrinter, 2, (LPBYTE)pInfo, infoSize, &numBytes)) { - ok = false; - } - }, { - GetPrinterA(hPrinter, 2, NULL, 0, &infoSize); - hMem = GlobalAlloc(GHND, infoSize); - pInfo = GlobalLock(hMem); - if (!GetPrinterA(hPrinter, 2, (LPBYTE)pInfo, infoSize, &numBytes)) { - ok = false; - } - }); + GetPrinter(hPrinter, 2, NULL, 0, &infoSize); + hMem = GlobalAlloc(GHND, infoSize); + pInfo = (PRINTER_INFO_2*) GlobalLock(hMem); + ok = GetPrinter(hPrinter, 2, (LPBYTE)pInfo, infoSize, &numBytes); if (!ok) { qErrnoWarning("QWin32PrintEngine::initialize: GetPrinter failed"); @@ -1073,28 +1014,15 @@ void QWin32PrintEnginePrivate::initialize() return; } - QT_WA( { - devMode = pInfoW()->pDevMode; - }, { - devMode = pInfoA()->pDevMode; - } ); - - QT_WA( { - hdc = CreateDC(reinterpret_cast(program.utf16()), - reinterpret_cast(name.utf16()), 0, devModeW()); - }, { - hdc = CreateDCA(program.toLatin1(), name.toLatin1(), 0, devModeA()); - } ); + devMode = pInfo->pDevMode; + hdc = CreateDC(reinterpret_cast(program.utf16()), + reinterpret_cast(name.utf16()), 0, devMode); Q_ASSERT(hPrinter); Q_ASSERT(pInfo); if (devMode) { - QT_WA( { - num_copies = devModeW()->dmCopies; - }, { - num_copies = devModeA()->dmCopies; - } ); + num_copies = devMode->dmCopies; } initHDC(); @@ -1212,28 +1140,18 @@ void QWin32PrintEnginePrivate::release() QList QWin32PrintEnginePrivate::queryResolutions() const { // Read the supported resolutions of the printer. - DWORD numRes; - LONG *enumRes; - DWORD errRes; QList list; - QT_WA({ - numRes = DeviceCapabilities(reinterpret_cast(name.utf16()), - reinterpret_cast(port.utf16()), - DC_ENUMRESOLUTIONS, 0, 0); - if (numRes == (DWORD)-1) - return list; - enumRes = (LONG*)malloc(numRes * 2 * sizeof(LONG)); - errRes = DeviceCapabilities(reinterpret_cast(name.utf16()), - reinterpret_cast(port.utf16()), - DC_ENUMRESOLUTIONS, (LPWSTR)enumRes, 0); - }, { - numRes = DeviceCapabilitiesA(name.toLocal8Bit(), port.toLocal8Bit(), DC_ENUMRESOLUTIONS, 0, 0); - if (numRes == (DWORD)-1) - return list; - enumRes = (LONG*)malloc(numRes * 2 * sizeof(LONG)); - errRes = DeviceCapabilitiesA(name.toLocal8Bit(), port.toLocal8Bit(), DC_ENUMRESOLUTIONS, (LPSTR)enumRes, 0); - }); + DWORD numRes = DeviceCapabilities(reinterpret_cast(name.utf16()), + reinterpret_cast(port.utf16()), + DC_ENUMRESOLUTIONS, 0, 0); + if (numRes == (DWORD)-1) + return list; + + LONG *enumRes = (LONG*)malloc(numRes * 2 * sizeof(LONG)); + DWORD errRes = DeviceCapabilities(reinterpret_cast(name.utf16()), + reinterpret_cast(port.utf16()), + DC_ENUMRESOLUTIONS, (LPWSTR)enumRes, 0); if (errRes == (DWORD)-1) { qErrnoWarning("QWin32PrintEngine::queryResolutions: DeviceCapabilities failed"); @@ -1241,7 +1159,8 @@ QList QWin32PrintEnginePrivate::queryResolutions() const } for (uint i=0; idevMode) break; - short collate = value.toBool() ? DMCOLLATE_TRUE : DMCOLLATE_FALSE; - QT_WA( { d->devModeW()->dmCollate = collate; }, - { d->devModeA()->dmCollate = collate; } ); + d->devMode->dmCollate = value.toBool() ? DMCOLLATE_TRUE : DMCOLLATE_FALSE; d->doReinit(); } break; @@ -1296,8 +1213,7 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant & { if (!d->devMode) break; - int cm = value.toInt() == QPrinter::Color ? DMCOLOR_COLOR : DMCOLOR_MONOCHROME; - QT_WA( { d->devModeW()->dmColor = cm; }, { d->devModeA()->dmColor = cm; } ); + d->devMode->dmColor = (value.toInt() == QPrinter::Color) ? DMCOLOR_COLOR : DMCOLOR_MONOCHROME; d->doReinit(); } break; @@ -1323,8 +1239,7 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant & if (!d->devMode) break; d->num_copies = value.toInt(); - QT_WA( { d->devModeW()->dmCopies = d->num_copies; }, - { d->devModeA()->dmCopies = d->num_copies; }); + d->devMode->dmCopies = d->num_copies; d->doReinit(); break; @@ -1333,14 +1248,8 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant & if (!d->devMode) break; int orientation = value.toInt() == QPrinter::Landscape ? DMORIENT_LANDSCAPE : DMORIENT_PORTRAIT; - int old_orientation; - QT_WA( { - old_orientation = d->devModeW()->dmOrientation; - d->devModeW()->dmOrientation = orientation; - }, { - old_orientation = d->devModeA()->dmOrientation; - d->devModeA()->dmOrientation = orientation; - } ); + int old_orientation = d->devMode->dmOrientation; + d->devMode->dmOrientation = orientation; if (d->has_custom_paper_size && old_orientation != orientation) d->paper_size = QSizeF(d->paper_size.height(), d->paper_size.width()); d->doReinit(); @@ -1359,11 +1268,7 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant & case PPK_PaperSize: if (!d->devMode) break; - QT_WA( { - d->devModeW()->dmPaperSize = mapPaperSizeDevmode(QPrinter::PaperSize(value.toInt())); - }, { - d->devModeA()->dmPaperSize = mapPaperSizeDevmode(QPrinter::PaperSize(value.toInt())); - } ); + d->devMode->dmPaperSize = mapPaperSizeDevmode(QPrinter::PaperSize(value.toInt())); d->has_custom_paper_size = (QPrinter::PaperSize(value.toInt()) == QPrinter::Custom); d->doReinit(); break; @@ -1378,11 +1283,7 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant & if (v.contains(value)) dmMapped = mapPaperSourceDevmode(QPrinter::PaperSource(value.toInt())); - QT_WA( { - d->devModeW()->dmDefaultSource = dmMapped; - }, { - d->devModeA()->dmDefaultSource = dmMapped; - } ); + d->devMode->dmDefaultSource = dmMapped; d->doReinit(); } break; @@ -1416,11 +1317,7 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant & if (!d->devMode) break; d->has_custom_paper_size = false; - QT_WA( { - d->devModeW()->dmPaperSize = value.toInt(); - }, { - d->devModeA()->dmPaperSize = value.toInt(); - } ); + d->devMode->dmPaperSize = value.toInt(); d->doReinit(); break; @@ -1430,33 +1327,28 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant & d->paper_size = value.toSizeF(); if (!d->devMode) break; - int orientation; - QT_WA( { - orientation = d->devModeW()->dmOrientation; - DWORD needed = 0; - DWORD returned = 0; - if (!EnumForms(d->hPrinter, 1, 0, 0, &needed, &returned)) { - BYTE *forms = (BYTE *) malloc(needed); - if (EnumForms(d->hPrinter, 1, forms, needed, &needed, &returned)) { - for (DWORD i=0; i< returned; ++i) { - FORM_INFO_1 *formArray = reinterpret_cast(forms); - // the form sizes are specified in 1000th of a mm, - // convert the size to Points - QSizeF size((formArray[i].Size.cx * 72/25.4)/1000.0, - (formArray[i].Size.cy * 72/25.4)/1000.0); - if (qAbs(d->paper_size.width() - size.width()) <= 2 - && qAbs(d->paper_size.height() - size.height()) <= 2) - { - d->devModeW()->dmPaperSize = i+1; - break; - } + int orientation = d->devMode->dmOrientation; + DWORD needed = 0; + DWORD returned = 0; + if (!EnumForms(d->hPrinter, 1, 0, 0, &needed, &returned)) { + BYTE *forms = (BYTE *) malloc(needed); + if (EnumForms(d->hPrinter, 1, forms, needed, &needed, &returned)) { + for (DWORD i=0; i< returned; ++i) { + FORM_INFO_1 *formArray = reinterpret_cast(forms); + // the form sizes are specified in 1000th of a mm, + // convert the size to Points + QSizeF size((formArray[i].Size.cx * 72/25.4)/1000.0, + (formArray[i].Size.cy * 72/25.4)/1000.0); + if (qAbs(d->paper_size.width() - size.width()) <= 2 + && qAbs(d->paper_size.height() - size.height()) <= 2) + { + d->devMode->dmPaperSize = i + 1; + break; } } - free(forms); } - }, { - orientation = d->devModeA()->dmOrientation; - } ); + free(forms); + } if (orientation != DMORIENT_PORTRAIT) d->paper_size = QSizeF(d->paper_size.height(), d->paper_size.width()); break; @@ -1496,13 +1388,7 @@ QVariant QWin32PrintEngine::property(PrintEnginePropertyKey key) const if (!d->devMode) { value = QPrinter::Color; } else { - int mode; - QT_WA( { - mode = d->devModeW()->dmColor; - }, { - mode = d->devModeA()->dmColor; - } ); - value = mode == DMCOLOR_COLOR ? QPrinter::Color : QPrinter::GrayScale; + value = (d->devMode->dmColor == DMCOLOR_COLOR) ? QPrinter::Color : QPrinter::GrayScale; } } break; @@ -1524,9 +1410,7 @@ QVariant QWin32PrintEngine::property(PrintEnginePropertyKey key) const if (!d->devMode) { value = QPrinter::Portrait; } else { - int o; - QT_WA( { o = d->devModeW()->dmOrientation; }, { o = d->devModeA()->dmOrientation; } ); - value = o == DMORIENT_LANDSCAPE ? QPrinter::Landscape : QPrinter::Portrait; + value = (d->devMode->dmOrientation == DMORIENT_LANDSCAPE) ? QPrinter::Landscape : QPrinter::Portrait; } } break; @@ -1560,11 +1444,7 @@ QVariant QWin32PrintEngine::property(PrintEnginePropertyKey key) const if (!d->devMode) { value = QPrinter::A4; } else { - QT_WA( { - value = mapDevmodePaperSize(d->devModeW()->dmPaperSize); - }, { - value = mapDevmodePaperSize(d->devModeA()->dmPaperSize); - } ); + value = mapDevmodePaperSize(d->devMode->dmPaperSize); } } break; @@ -1583,11 +1463,7 @@ QVariant QWin32PrintEngine::property(PrintEnginePropertyKey key) const if (!d->devMode) { value = QPrinter::Auto; } else { - QT_WA( { - value = mapDevmodePaperSource(d->devModeW()->dmDefaultSource); - }, { - value = mapDevmodePaperSource(d->devModeA()->dmDefaultSource); - } ); + value = mapDevmodePaperSource(d->devMode->dmDefaultSource); } break; @@ -1608,38 +1484,21 @@ QVariant QWin32PrintEngine::property(PrintEnginePropertyKey key) const if (!d->devMode) { value = -1; } else { - QT_WA( { - value = d->devModeW()->dmPaperSize; - }, { - value = d->devModeA()->dmPaperSize; - } ); + value = d->devMode->dmPaperSize; } break; case PPK_PaperSources: { - int available, count; - WORD *data; - - QT_WA({ - available = DeviceCapabilitiesW((const WCHAR *)d->name.utf16(), (const WCHAR *)d->port.utf16(), DC_BINS, 0, - d->devModeW()); - }, { - available = DeviceCapabilitiesA(d->name.toLatin1(), d->port.toLatin1(), DC_BINS, 0, - d->devModeA()); - }); + int available = DeviceCapabilities((const wchar_t *)d->name.utf16(), + (const wchar_t *)d->port.utf16(), DC_BINS, 0, d->devMode); if (available <= 0) break; - data = (WORD *) malloc(available * sizeof(WORD)); - QT_WA({ - count = DeviceCapabilitiesW((const WCHAR *)d->name.utf16(), (const WCHAR *)d->port.utf16(), DC_BINS, (WCHAR *)data, - d->devModeW()); - }, { - count = DeviceCapabilitiesA(d->name.toLatin1(), d->port.toLatin1(), DC_BINS, - (char *) data, d->devModeA()); - }); + wchar_t *data = new wchar_t[available]; + int count = DeviceCapabilities((const wchar_t *)d->name.utf16(), + (const wchar_t *)d->port.utf16(), DC_BINS, data, d->devMode); QList out; for (int i=0; iwDriverOffset = sizeof(DEVNAMES) / sizeof(TCHAR); - dn->wDeviceOffset = dn->wDriverOffset + program.length() + 1; - dn->wOutputOffset = dn->wDeviceOffset + name.length() + 1; + dn->wDriverOffset = sizeof(DEVNAMES) / sizeof(wchar_t); + dn->wDeviceOffset = dn->wDriverOffset + program.length() + 1; + dn->wOutputOffset = dn->wDeviceOffset + name.length() + 1; - memcpy((ushort*)dn + dn->wDriverOffset, program.utf16(), program.length() * 2 + 2); - memcpy((ushort*)dn + dn->wDeviceOffset, name.utf16(), name.length() * 2 + 2); - memcpy((ushort*)dn + dn->wOutputOffset, port.utf16(), port.length() * 2 + 2); - dn->wDefault = 0; + memcpy((ushort*)dn + dn->wDriverOffset, program.utf16(), program.length() * 2 + 2); + memcpy((ushort*)dn + dn->wDeviceOffset, name.utf16(), name.length() * 2 + 2); + memcpy((ushort*)dn + dn->wOutputOffset, port.utf16(), port.length() * 2 + 2); + dn->wDefault = 0; - GlobalUnlock(hGlobal); + GlobalUnlock(hGlobal); // printf("QPrintDialogWinPrivate::createDevNames()\n" // " -> wDriverOffset: %d\n" @@ -1721,89 +1580,46 @@ HGLOBAL *QWin32PrintEnginePrivate::createDevNames() // dn->wOutputOffset); // printf("QPrintDialogWinPrivate::createDevNames(): %s, %s, %s\n", -// QString::fromUtf16((ushort*)(dn) + dn->wDriverOffset).latin1(), -// QString::fromUtf16((ushort*)(dn) + dn->wDeviceOffset).latin1(), -// QString::fromUtf16((ushort*)(dn) + dn->wOutputOffset).latin1()); - - return hGlobal; - }, { - int size = sizeof(DEVNAMES) - + program.length() + 2 - + name.length() + 2 - + port.length() + 2; - HGLOBAL *hGlobal = (HGLOBAL *) GlobalAlloc(GMEM_MOVEABLE, size); - DEVNAMES *dn = (DEVNAMES*) GlobalLock(hGlobal); - - dn->wDriverOffset = sizeof(DEVNAMES); - dn->wDeviceOffset = dn->wDriverOffset + program.length() + 1; - dn->wOutputOffset = dn->wDeviceOffset + name.length() + 1; - - memcpy((char*)dn + dn->wDriverOffset, program.toLatin1(), program.length() + 2); - memcpy((char*)dn + dn->wDeviceOffset, name.toLatin1(), name.length() + 2); - memcpy((char*)dn + dn->wOutputOffset, port.toLatin1(), port.length() + 2); - dn->wDefault = 0; - - GlobalUnlock(hGlobal); - return hGlobal; - } ); +// QString::fromWCharArray((wchar_t*)(dn) + dn->wDriverOffset).latin1(), +// QString::fromWCharArray((wchar_t*)(dn) + dn->wDeviceOffset).latin1(), +// QString::fromWCharArray((wchar_t*)(dn) + dn->wOutputOffset).latin1()); + + return hGlobal; } void QWin32PrintEnginePrivate::readDevnames(HGLOBAL globalDevnames) { if (globalDevnames) { - QT_WA( { - DEVNAMES *dn = (DEVNAMES*) GlobalLock(globalDevnames); - name = QString::fromUtf16((ushort*)(dn) + dn->wDeviceOffset); - port = QString::fromUtf16((ushort*)(dn) + dn->wOutputOffset); - program = QString::fromUtf16((ushort*)(dn) + dn->wDriverOffset); - GlobalUnlock(globalDevnames); - }, { - DEVNAMES *dn = (DEVNAMES*) GlobalLock(globalDevnames); - name = QString::fromLatin1((char*)(dn) + dn->wDeviceOffset); - port = QString::fromLatin1((char*)(dn) + dn->wOutputOffset); - program = QString::fromLatin1((char*)(dn) + dn->wDriverOffset); - GlobalUnlock(globalDevnames); - } ); + DEVNAMES *dn = (DEVNAMES*) GlobalLock(globalDevnames); + name = QString::fromWCharArray((wchar_t*)(dn) + dn->wDeviceOffset); + port = QString::fromWCharArray((wchar_t*)(dn) + dn->wOutputOffset); + program = QString::fromWCharArray((wchar_t*)(dn) + dn->wDriverOffset); + GlobalUnlock(globalDevnames); } } void QWin32PrintEnginePrivate::readDevmode(HGLOBAL globalDevmode) { if (globalDevmode) { - QT_WA( { - DEVMODE *dm = (DEVMODE*) GlobalLock(globalDevmode); - release(); - globalDevMode = globalDevmode; - devMode = dm; - hdc = CreateDC(reinterpret_cast(program.utf16()), - reinterpret_cast(name.utf16()), 0, dm); - - num_copies = devModeW()->dmCopies; - if (!OpenPrinterW((LPWSTR)name.utf16(), (LPHANDLE)&hPrinter, 0)) - qWarning("QPrinter: OpenPrinter() failed after reading DEVMODE."); - }, { - DEVMODEA *dm = (DEVMODEA*) GlobalLock(globalDevmode); - release(); - globalDevMode = globalDevmode; - devMode = dm; - hdc = CreateDCA(program.toLatin1(), name.toLatin1(), 0, dm); - - num_copies = devModeA()->dmCopies; - if (!OpenPrinterA((LPSTR)name.toLatin1().data(), (LPHANDLE)&hPrinter, 0)) - qWarning("QPrinter: OpenPrinter() failed after reading DEVMODE."); - } ); + DEVMODE *dm = (DEVMODE*) GlobalLock(globalDevmode); + release(); + globalDevMode = globalDevmode; + devMode = dm; + hdc = CreateDC(reinterpret_cast(program.utf16()), + reinterpret_cast(name.utf16()), 0, dm); + + num_copies = devMode->dmCopies; + if (!OpenPrinter((wchar_t*)name.utf16(), &hPrinter, 0)) + qWarning("QPrinter: OpenPrinter() failed after reading DEVMODE."); } if (hdc) initHDC(); } -static void draw_text_item_win(const QPointF &_pos, const QTextItemInt &ti, HDC hdc, +static void draw_text_item_win(const QPointF &pos, const QTextItemInt &ti, HDC hdc, bool convertToText, const QTransform &xform, const QPointF &topLeft) { - - // Make sure we translate for systems that can't handle world transforms - QPointF pos(QT_WA_INLINE(_pos, _pos + QPointF(xform.dx(), xform.dy()))); QFontEngine *fe = ti.fontEngine; QPointF baseline_pos = xform.inverted().map(xform.map(pos) - topLeft); @@ -1815,12 +1631,10 @@ static void draw_text_item_win(const QPointF &_pos, const QTextItemInt &ti, HDC HFONT hfont; bool ttf = false; - bool useTextOutA = false; if (winfe) { hfont = winfe->hfont; ttf = winfe->ttf; - useTextOutA = winfe->useTextOutA; } else { hfont = (HFONT)GetStockObject(ANSI_VAR_FONT); } @@ -1830,153 +1644,115 @@ static void draw_text_item_win(const QPointF &_pos, const QTextItemInt &ti, HDC wchar_t *convertedGlyphs = (wchar_t *)ti.chars; QGlyphLayout glyphs = ti.glyphs; - if (!(ti.flags & QTextItem::RightToLeft) && useTextOutA) { - qreal x = pos.x(); - qreal y = pos.y(); - - // hack to get symbol fonts working on Win95. See also QFontEngine constructor - // can only happen if !ttf - for(int i = 0; i < glyphs.numGlyphs; i++) { - QString str(QChar(glyphs.glyphs[i])); - QT_WA({ - TextOutW(hdc, qRound(x + glyphs.offsets[i].x.toReal()), - qRound(y + glyphs.offsets[i].y.toReal()), - (LPWSTR)str.utf16(), str.length()); - } , { - QByteArray cstr = str.toLocal8Bit(); - TextOutA(hdc, qRound(x + glyphs.offsets[i].x.toReal()), - qRound(y + glyphs.offsets[i].y.toReal()), - cstr.data(), cstr.length()); - }); - x += glyphs.effectiveAdvance(i).toReal(); - } - } else { - bool fast = !has_kerning && !(ti.flags & QTextItem::RightToLeft); - for(int i = 0; fast && i < glyphs.numGlyphs; i++) { - if (glyphs.offsets[i].x != 0 || glyphs.offsets[i].y != 0 || glyphs.justifications[i].space_18d6 != 0 - || glyphs.attributes[i].dontPrint) { - fast = false; - break; - } + bool fast = !has_kerning && !(ti.flags & QTextItem::RightToLeft); + for (int i = 0; fast && i < glyphs.numGlyphs; i++) { + if (glyphs.offsets[i].x != 0 || glyphs.offsets[i].y != 0 || glyphs.justifications[i].space_18d6 != 0 + || glyphs.attributes[i].dontPrint) { + fast = false; + break; } + } #if !defined(Q_OS_WINCE) - // Scale, rotate and translate here. This is only valid for systems > Windows Me. - // We should never get here on Windows Me or lower if the transformation specifies - // scaling or rotation. - QT_WA({ - XFORM win_xform; - win_xform.eM11 = xform.m11(); - win_xform.eM12 = xform.m12(); - win_xform.eM21 = xform.m21(); - win_xform.eM22 = xform.m22(); - win_xform.eDx = xform.dx(); - win_xform.eDy = xform.dy(); - SetGraphicsMode(hdc, GM_ADVANCED); - SetWorldTransform(hdc, &win_xform); - }, { - // nothing - }); + // Scale, rotate and translate here. + XFORM win_xform; + win_xform.eM11 = xform.m11(); + win_xform.eM12 = xform.m12(); + win_xform.eM21 = xform.m21(); + win_xform.eM22 = xform.m22(); + win_xform.eDx = xform.dx(); + win_xform.eDy = xform.dy(); + + SetGraphicsMode(hdc, GM_ADVANCED); + SetWorldTransform(hdc, &win_xform); #endif - if (fast) { - // fast path - QVarLengthArray g(glyphs.numGlyphs); - for (int i = 0; i < glyphs.numGlyphs; ++i) - g[i] = glyphs.glyphs[i]; - ExtTextOutW(hdc, - qRound(baseline_pos.x() + glyphs.offsets[0].x.toReal()), - qRound(baseline_pos.y() + glyphs.offsets[0].y.toReal()), - options, 0, convertToText ? convertedGlyphs : g.data(), glyphs.numGlyphs, 0); - } else { - QVarLengthArray positions; - QVarLengthArray _glyphs; - - QTransform matrix = QTransform::fromTranslate(baseline_pos.x(), baseline_pos.y()); - ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, - _glyphs, positions); - if (_glyphs.size() == 0) { - SelectObject(hdc, old_font); - return; - } - - convertToText = convertToText && glyphs.numGlyphs == _glyphs.size(); - - bool outputEntireItem = (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based) - && QSysInfo::WindowsVersion != QSysInfo::WV_NT - && _glyphs.size() > 0; + if (fast) { + // fast path + QVarLengthArray g(glyphs.numGlyphs); + for (int i = 0; i < glyphs.numGlyphs; ++i) + g[i] = glyphs.glyphs[i]; + ExtTextOut(hdc, + qRound(baseline_pos.x() + glyphs.offsets[0].x.toReal()), + qRound(baseline_pos.y() + glyphs.offsets[0].y.toReal()), + options, 0, convertToText ? convertedGlyphs : g.data(), glyphs.numGlyphs, 0); + } else { + QVarLengthArray positions; + QVarLengthArray _glyphs; + + QTransform matrix = QTransform::fromTranslate(baseline_pos.x(), baseline_pos.y()); + ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, + _glyphs, positions); + if (_glyphs.size() == 0) { + SelectObject(hdc, old_font); + return; + } - if (outputEntireItem) { - options |= ETO_PDY; - QVarLengthArray glyphDistances(_glyphs.size() * 2); - QVarLengthArray g(_glyphs.size()); - for (int i=0; i<_glyphs.size() - 1; ++i) { - glyphDistances[i * 2] = qRound(positions[i + 1].x) - qRound(positions[i].x); - glyphDistances[i * 2 + 1] = qRound(positions[i + 1].y) - qRound(positions[i].y); - g[i] = _glyphs[i]; - } - glyphDistances[(_glyphs.size() - 1) * 2] = 0; - glyphDistances[(_glyphs.size() - 1) * 2 + 1] = 0; - g[_glyphs.size() - 1] = _glyphs[_glyphs.size() - 1]; - ExtTextOutW(hdc, qRound(positions[0].x), qRound(positions[0].y), options, 0, - convertToText ? convertedGlyphs : g.data(), _glyphs.size(), - glyphDistances.data()); - } else { - int i = 0; - while(i < _glyphs.size()) { - wchar_t g = _glyphs[i]; - - ExtTextOutW(hdc, qRound(positions[i].x), - qRound(positions[i].y), options, 0, - convertToText ? convertedGlyphs + i : &g, 1, 0); - ++i; - } + convertToText = convertToText && glyphs.numGlyphs == _glyphs.size(); + bool outputEntireItem = _glyphs.size() > 0; + + if (outputEntireItem) { + options |= ETO_PDY; + QVarLengthArray glyphDistances(_glyphs.size() * 2); + QVarLengthArray g(_glyphs.size()); + for (int i=0; i<_glyphs.size() - 1; ++i) { + glyphDistances[i * 2] = qRound(positions[i + 1].x) - qRound(positions[i].x); + glyphDistances[i * 2 + 1] = qRound(positions[i + 1].y) - qRound(positions[i].y); + g[i] = _glyphs[i]; + } + glyphDistances[(_glyphs.size() - 1) * 2] = 0; + glyphDistances[(_glyphs.size() - 1) * 2 + 1] = 0; + g[_glyphs.size() - 1] = _glyphs[_glyphs.size() - 1]; + ExtTextOut(hdc, qRound(positions[0].x), qRound(positions[0].y), options, 0, + convertToText ? convertedGlyphs : g.data(), _glyphs.size(), + glyphDistances.data()); + } else { + int i = 0; + while(i < _glyphs.size()) { + wchar_t g = _glyphs[i]; + + ExtTextOut(hdc, qRound(positions[i].x), + qRound(positions[i].y), options, 0, + convertToText ? convertedGlyphs + i : &g, 1, 0); + ++i; } } + } #if !defined(Q_OS_WINCE) - QT_WA({ - XFORM win_xform; - win_xform.eM11 = win_xform.eM22 = 1.0; - win_xform.eM12 = win_xform.eM21 = win_xform.eDx = win_xform.eDy = 0.0; - SetWorldTransform(hdc, &win_xform); - }, { - // nothing - }); + win_xform.eM11 = win_xform.eM22 = 1.0; + win_xform.eM12 = win_xform.eM21 = win_xform.eDx = win_xform.eDy = 0.0; + SetWorldTransform(hdc, &win_xform); #endif - } + SelectObject(hdc, old_font); } void QWin32PrintEnginePrivate::updateCustomPaperSize() { - QT_WA( { - uint paperSize = devModeW()->dmPaperSize; - if (paperSize > 0 && mapDevmodePaperSize(paperSize) == QPrinter::Custom) { - has_custom_paper_size = true; - DWORD needed = 0; - DWORD returned = 0; - if (!EnumForms(hPrinter, 1, 0, 0, &needed, &returned)) { - BYTE *forms = (BYTE *) malloc(needed); - if (EnumForms(hPrinter, 1, forms, needed, &needed, &returned)) { - if (paperSize <= returned) { - FORM_INFO_1 *formArray = (FORM_INFO_1 *) forms; - int width = formArray[paperSize-1].Size.cx; // 1/1000 of a mm - int height = formArray[paperSize-1].Size.cy; // 1/1000 of a mm - paper_size = QSizeF((width*72/25.4)/1000.0, (height*72/25.4)/1000.0); - } else { - has_custom_paper_size = false; - } + uint paperSize = devMode->dmPaperSize; + if (paperSize > 0 && mapDevmodePaperSize(paperSize) == QPrinter::Custom) { + has_custom_paper_size = true; + DWORD needed = 0; + DWORD returned = 0; + if (!EnumForms(hPrinter, 1, 0, 0, &needed, &returned)) { + BYTE *forms = (BYTE *) malloc(needed); + if (EnumForms(hPrinter, 1, forms, needed, &needed, &returned)) { + if (paperSize <= returned) { + FORM_INFO_1 *formArray = (FORM_INFO_1 *) forms; + int width = formArray[paperSize - 1].Size.cx; // 1/1000 of a mm + int height = formArray[paperSize - 1].Size.cy; // 1/1000 of a mm + paper_size = QSizeF((width * 72 /25.4) / 1000.0, (height * 72 / 25.4) / 1000.0); + } else { + has_custom_paper_size = false; } - free(forms); } - } else { - has_custom_paper_size = false; + free(forms); } - }, { - // Not supported under Win98 - } ); + } else { + has_custom_paper_size = false; + } } QT_END_NAMESPACE diff --git a/src/gui/painting/qprintengine_win_p.h b/src/gui/painting/qprintengine_win_p.h index 9eb0b69..36a32e8 100644 --- a/src/gui/painting/qprintengine_win_p.h +++ b/src/gui/painting/qprintengine_win_p.h @@ -169,18 +169,8 @@ public: void readDevmode(HGLOBAL globalDevmode); void readDevnames(HGLOBAL globalDevnames); - inline DEVMODEW *devModeW() const { return (DEVMODEW*) devMode; } - inline DEVMODEA *devModeA() const { return (DEVMODEA*) devMode; } - - inline PRINTER_INFO_2W *pInfoW() { return (PRINTER_INFO_2W*) pInfo; }; - inline PRINTER_INFO_2A *pInfoA() { return (PRINTER_INFO_2A*) pInfo; }; - inline bool resetDC() { - QT_WA( { - hdc = ResetDCW(hdc, devModeW()); - }, { - hdc = ResetDCA(hdc, devModeA()); - } ); + hdc = ResetDC(hdc, devMode); return hdc != 0; } @@ -202,8 +192,8 @@ public: HANDLE hPrinter; HGLOBAL globalDevMode; - void *devMode; - void *pInfo; + DEVMODE *devMode; + PRINTER_INFO_2 *pInfo; HGLOBAL hMem; HDC hdc; diff --git a/src/gui/painting/qprinterinfo_win.cpp b/src/gui/painting/qprinterinfo_win.cpp index f0352e6..a10cf3f 100644 --- a/src/gui/painting/qprinterinfo_win.cpp +++ b/src/gui/painting/qprinterinfo_win.cpp @@ -79,45 +79,24 @@ QList QPrinterInfo::availablePrinters() DWORD needed = 0; DWORD returned = 0; - QT_WA({ - if (!EnumPrintersW(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, - 4, 0, 0, &needed, &returned)) - { - buffer = new BYTE[needed]; - if (!EnumPrintersW(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS , NULL, - 4, buffer, needed, &needed, &returned)) - { - delete [] buffer; - return printers; - } - PPRINTER_INFO_4 infoList = reinterpret_cast(buffer); - QPrinterInfo defPrn = defaultPrinter(); - for (uint i = 0; i < returned; ++i) { - printers.append(QPrinterInfo(QString::fromUtf16(reinterpret_cast(infoList[i].pPrinterName)))); - if (printers.at(i).printerName() == defPrn.printerName()) - printers[i].d_ptr->m_default = true; - } - delete [] buffer; - } - }, { - // In Windows 98 networked printers are served through the local connection - if (!EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 5, 0, 0, &needed, &returned)) { - buffer = new BYTE[needed]; - if (!EnumPrintersA(PRINTER_ENUM_LOCAL, NULL, 5, buffer, needed, &needed, &returned)) { - delete [] buffer; - return printers; - } - - PPRINTER_INFO_5 infoList = reinterpret_cast(buffer); - QPrinterInfo defPrn = defaultPrinter(); - for (uint i = 0; i < returned; ++i) { - printers.append(QPrinterInfo(QString::fromLocal8Bit(reinterpret_cast(infoList[i].pPrinterName)))); - if (printers.at(i).printerName() == defPrn.printerName()) - printers[i].d_ptr->m_default = true; - } - delete [] buffer; - } - }); + if ( !EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 4, 0, 0, &needed, &returned)) + { + buffer = new BYTE[needed]; + if (!EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS , NULL, + 4, buffer, needed, &needed, &returned)) + { + delete [] buffer; + return printers; + } + PPRINTER_INFO_4 infoList = reinterpret_cast(buffer); + QPrinterInfo defPrn = defaultPrinter(); + for (uint i = 0; i < returned; ++i) { + printers.append(QPrinterInfo(QString::fromWCharArray(infoList[i].pPrinterName))); + if (printers.at(i).printerName() == defPrn.printerName()) + printers[i].d_ptr->m_default = true; + } + delete [] buffer; + } return printers; } @@ -125,18 +104,9 @@ QList QPrinterInfo::availablePrinters() QPrinterInfo QPrinterInfo::defaultPrinter() { QString noPrinters(QLatin1String("qt_no_printers")); - QString output; - QT_WA({ - ushort buffer[256]; - GetProfileStringW(L"windows", L"device", - reinterpret_cast(noPrinters.utf16()), - reinterpret_cast(buffer), 256); - output = QString::fromUtf16(buffer); - }, { - char buffer[256]; - GetProfileStringA("windows", "device", noPrinters.toLatin1(), buffer, 256); - output = QString::fromLocal8Bit(buffer); - }); + wchar_t buffer[256]; + GetProfileString(L"windows", L"device", (wchar_t*)noPrinters.utf16(), buffer, 256); + QString output = QString::fromWCharArray(buffer); // Filter out the name of the printer, which should be everything // before a comma. @@ -222,26 +192,16 @@ bool QPrinterInfo::isDefault() const QList QPrinterInfo::supportedPaperSizes() const { const Q_D(QPrinterInfo); - DWORD size; - WORD* papers; QList paperList; - QT_WA({ - size = DeviceCapabilitiesW(reinterpret_cast(d->m_name.utf16()), - NULL, DC_PAPERS, NULL, NULL); - if ((int)size == -1) - return paperList; - papers = new WORD[size]; - size = DeviceCapabilitiesW(reinterpret_cast(d->m_name.utf16()), - NULL, DC_PAPERS, reinterpret_cast(papers), NULL); - }, { - size = DeviceCapabilitiesA(d->m_name.toLatin1().data(), NULL, DC_PAPERS, NULL, NULL); - if ((int)size == -1) - return paperList; - papers = new WORD[size]; - size = DeviceCapabilitiesA(d->m_name.toLatin1().data(), NULL, DC_PAPERS, - reinterpret_cast(papers), NULL); - }); + DWORD size = DeviceCapabilities(reinterpret_cast(d->m_name.utf16()), + NULL, DC_PAPERS, NULL, NULL); + if ((int)size == -1) + return paperList; + + wchar_t *papers = new wchar_t[size]; + size = DeviceCapabilities(reinterpret_cast(d->m_name.utf16()), + NULL, DC_PAPERS, papers, NULL); for (int c = 0; c < (int)size; ++c) { paperList.append(mapDevmodePaperSize(papers[c])); diff --git a/src/gui/painting/qregion.cpp b/src/gui/painting/qregion.cpp index 1b7dc1b..762e9e0 100644 --- a/src/gui/painting/qregion.cpp +++ b/src/gui/painting/qregion.cpp @@ -92,10 +92,6 @@ QT_BEGIN_NAMESPACE Example of using complex regions: \snippet doc/src/snippets/code/src_gui_painting_qregion.cpp 0 - \warning Due to window system limitations, the whole coordinate space for a - region is limited to the points between -32767 and 32767 on Windows - 95/98/ME. You can circumvent this limitation by using a QPainterPath. - \section1 Additional License Information On Embedded Linux, Windows CE and X11 platforms, parts of this class rely on diff --git a/src/gui/painting/qwindowsurface_raster.cpp b/src/gui/painting/qwindowsurface_raster.cpp index c163d79..22433dd 100644 --- a/src/gui/painting/qwindowsurface_raster.cpp +++ b/src/gui/painting/qwindowsurface_raster.cpp @@ -43,6 +43,7 @@ #include // for Q_WS_WIN define (non-PCH) #ifdef Q_WS_WIN +#include #include #endif @@ -67,10 +68,6 @@ QT_BEGIN_NAMESPACE -#ifdef Q_WS_WIN -PtrUpdateLayeredWindowIndirect ptrUpdateLayeredWindowIndirect; -#endif - class QRasterWindowSurfacePrivate { public: @@ -82,9 +79,6 @@ public: uint translucentBackground : 1; #endif #endif -#if defined(Q_WS_WIN) && !defined(Q_WS_WINCE) - uint canUseLayeredWindow : 1; -#endif uint inSetGeometry : 1; }; @@ -98,10 +92,6 @@ QRasterWindowSurface::QRasterWindowSurface(QWidget *window) && window->x11Info().depth() == 32; #endif #endif -#if defined(Q_WS_WIN) && !defined(Q_WS_WINCE) - d_ptr->canUseLayeredWindow = ptrUpdateLayeredWindowIndirect - && (qt_widget_private(window)->data.window_flags & Qt::FramelessWindowHint); -#endif d_ptr->image = 0; d_ptr->inSetGeometry = false; setStaticContentsSupport(true); @@ -130,8 +120,7 @@ void QRasterWindowSurface::beginPaint(const QRegion &rgn) #if (defined(Q_WS_X11) && !defined(QT_NO_XRENDER)) || (defined(Q_WS_WIN) && !defined(Q_WS_WINCE)) if (!qt_widget_private(window())->isOpaque) { #if defined(Q_WS_WIN) && !defined(Q_WS_WINCE) - if (d_ptr->image->image.format() != QImage::Format_ARGB32_Premultiplied - && d_ptr->canUseLayeredWindow) + if (d_ptr->image->image.format() != QImage::Format_ARGB32_Premultiplied) prepareBuffer(QImage::Format_ARGB32_Premultiplied, window()); #endif QPainter p(&d_ptr->image->image); @@ -160,7 +149,7 @@ void QRasterWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoi QRect br = rgn.boundingRect(); #ifndef Q_WS_WINCE - if (!qt_widget_private(window())->isOpaque && d->canUseLayeredWindow) { + if (!qt_widget_private(window())->isOpaque) { QRect r = window()->frameGeometry(); QPoint frameOffset = qt_widget_private(window())->frameStrut().topLeft(); QRect dirtyRect = br.translated(offset + frameOffset); @@ -168,12 +157,11 @@ void QRasterWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoi SIZE size = {r.width(), r.height()}; POINT ptDst = {r.x(), r.y()}; POINT ptSrc = {0, 0}; - Q_BLENDFUNCTION blend = {AC_SRC_OVER, 0, (int)(255.0 * window()->windowOpacity()), Q_AC_SRC_ALPHA}; + BLENDFUNCTION blend = {AC_SRC_OVER, 0, (int)(255.0 * window()->windowOpacity()), Q_AC_SRC_ALPHA}; RECT dirty = {dirtyRect.x(), dirtyRect.y(), dirtyRect.x() + dirtyRect.width(), dirtyRect.y() + dirtyRect.height()}; Q_UPDATELAYEREDWINDOWINFO info = {sizeof(info), NULL, &ptDst, &size, d->image->hdc, &ptSrc, 0, &blend, Q_ULW_ALPHA, &dirty}; - - (*ptrUpdateLayeredWindowIndirect)(window()->internalWinId(), &info); + ptrUpdateLayeredWindowIndirect(window()->internalWinId(), &info); } else #endif { @@ -308,7 +296,7 @@ void QRasterWindowSurface::setGeometry(const QRect &rect) #ifndef Q_WS_WIN if (d_ptr->translucentBackground) #else - if (!qt_widget_private(window())->isOpaque && d->canUseLayeredWindow) + if (!qt_widget_private(window())->isOpaque) #endif prepareBuffer(QImage::Format_ARGB32_Premultiplied, window()); else diff --git a/src/gui/painting/qwindowsurface_raster_p.h b/src/gui/painting/qwindowsurface_raster_p.h index 897ed8d..996aaef 100644 --- a/src/gui/painting/qwindowsurface_raster_p.h +++ b/src/gui/painting/qwindowsurface_raster_p.h @@ -64,13 +64,6 @@ QT_BEGIN_NAMESPACE #define Q_ULW_ALPHA 0x00000002 // copied from ULW_ALPHA in winuser.h #define Q_AC_SRC_ALPHA 0x00000001 // copied from AC_SRC_ALPHA in winuser.h -struct Q_BLENDFUNCTION { - BYTE BlendOp; - BYTE BlendFlags; - BYTE SourceConstantAlpha; - BYTE AlphaFormat; -}; - struct Q_UPDATELAYEREDWINDOWINFO { DWORD cbSize; HDC hdcDst; @@ -79,12 +72,16 @@ struct Q_UPDATELAYEREDWINDOWINFO { HDC hdcSrc; const POINT *pptSrc; COLORREF crKey; - const Q_BLENDFUNCTION *pblend; + const BLENDFUNCTION *pblend; DWORD dwFlags; const RECT *prcDirty; }; +typedef BOOL (WINAPI *PtrUpdateLayeredWindow)(HWND hwnd, HDC hdcDst, const POINT *pptDst, + const SIZE *psize, HDC hdcSrc, const POINT *pptSrc, COLORREF crKey, + const BLENDFUNCTION *pblend, DWORD dwflags); typedef BOOL (WINAPI *PtrUpdateLayeredWindowIndirect)(HWND hwnd, const Q_UPDATELAYEREDWINDOWINFO *pULWInfo); +extern PtrUpdateLayeredWindow ptrUpdateLayeredWindow; extern PtrUpdateLayeredWindowIndirect ptrUpdateLayeredWindowIndirect; #endif diff --git a/src/gui/styles/qwindowsstyle.cpp b/src/gui/styles/qwindowsstyle.cpp index 997c2ce..4f25e68 100644 --- a/src/gui/styles/qwindowsstyle.cpp +++ b/src/gui/styles/qwindowsstyle.cpp @@ -126,8 +126,6 @@ static const int windowsCheckMarkHMargin = 2; // horiz. margins of check mark static const int windowsRightBorder = 15; // right border on windows static const int windowsCheckMarkWidth = 12; // checkmarks width on windows -static bool use2000style = true; - enum QSliderDirection { SlUp, SlDown, SlLeft, SlRight }; /* @@ -269,9 +267,6 @@ bool QWindowsStyle::eventFilter(QObject *o, QEvent *e) */ QWindowsStyle::QWindowsStyle() : QCommonStyle(*new QWindowsStylePrivate) { -#if defined(Q_OS_WIN32) - use2000style = QSysInfo::WindowsVersion != QSysInfo::WV_NT && QSysInfo::WindowsVersion != QSysInfo::WV_95; -#endif } /*! @@ -281,9 +276,6 @@ QWindowsStyle::QWindowsStyle() : QCommonStyle(*new QWindowsStylePrivate) */ QWindowsStyle::QWindowsStyle(QWindowsStylePrivate &dd) : QCommonStyle(dd) { -#if defined(Q_OS_WIN32) - use2000style = QSysInfo::WindowsVersion != QSysInfo::WV_NT && QSysInfo::WindowsVersion != QSysInfo::WV_95; -#endif } @@ -1137,12 +1129,7 @@ int QWindowsStyle::styleHint(StyleHint hint, const QStyleOption *opt, const QWid #endif break; case SH_ItemView_ChangeHighlightOnFocus: -#if defined(Q_WS_WIN) - if (QSysInfo::WindowsVersion != QSysInfo::WV_95 && QSysInfo::WindowsVersion != QSysInfo::WV_NT) - ret = 1; - else -#endif - ret = 0; + ret = 1; break; case SH_ToolBox_SelectedPageTitleBold: ret = 0; @@ -1150,36 +1137,34 @@ int QWindowsStyle::styleHint(StyleHint hint, const QStyleOption *opt, const QWid #if defined(Q_WS_WIN) case SH_UnderlineShortcut: + { ret = 1; - if (QSysInfo::WindowsVersion != QSysInfo::WV_95 - && QSysInfo::WindowsVersion != QSysInfo::WV_98 - && QSysInfo::WindowsVersion != QSysInfo::WV_NT) { - BOOL cues; - SystemParametersInfo(SPI_GETKEYBOARDCUES, 0, &cues, 0); - ret = int(cues); - // Do nothing if we always paint underlines - Q_D(const QWindowsStyle); - if (!ret && widget && d) { + BOOL cues = false; + SystemParametersInfo(SPI_GETKEYBOARDCUES, 0, &cues, 0); + ret = int(cues); + // Do nothing if we always paint underlines + Q_D(const QWindowsStyle); + if (!ret && widget && d) { #ifndef QT_NO_MENUBAR - const QMenuBar *menuBar = qobject_cast(widget); - if (!menuBar && qobject_cast(widget)) { - QWidget *w = QApplication::activeWindow(); - if (w && w != widget) - menuBar = qFindChild(w); - } - // If we paint a menu bar draw underlines if is in the keyboardState - if (menuBar) { - if (menuBar->d_func()->keyboardState || d->altDown()) - ret = 1; - // Otherwise draw underlines if the toplevel widget has seen an alt-press - } else -#endif // QT_NO_MENUBAR - if (d->hasSeenAlt(widget)) { + const QMenuBar *menuBar = qobject_cast(widget); + if (!menuBar && qobject_cast(widget)) { + QWidget *w = QApplication::activeWindow(); + if (w && w != widget) + menuBar = qFindChild(w); + } + // If we paint a menu bar draw underlines if is in the keyboardState + if (menuBar) { + if (menuBar->d_func()->keyboardState || d->altDown()) ret = 1; - } + // Otherwise draw underlines if the toplevel widget has seen an alt-press + } else +#endif // QT_NO_MENUBAR + if (d->hasSeenAlt(widget)) { + ret = 1; } } break; + } #endif #ifndef QT_NO_RUBBERBAND case SH_RubberBand_Mask: @@ -1317,7 +1302,7 @@ void QWindowsStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, if ((!(opt->state & State_Sunken )) && (!(opt->state & State_Enabled) || !(opt->state & State_MouseOver && opt->state & State_AutoRaise)) - && (opt->state & State_On) && use2000style) { + && (opt->state & State_On)) { fill = QBrush(opt->palette.light().color(), Qt::Dense4Pattern); stippled = true; } else { @@ -1631,9 +1616,9 @@ void QWindowsStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, popupPal.setColor(QPalette::Light, frame->palette.background().color()); popupPal.setColor(QPalette::Midlight, frame->palette.light().color()); } - if (use2000style && pe == PE_Frame && (frame->state & State_Raised)) + if (pe == PE_Frame && (frame->state & State_Raised)) qDrawWinButton(p, frame->rect, popupPal, frame->state & State_Sunken); - else if (use2000style && pe == PE_Frame && (frame->state & State_Sunken)) + else if (pe == PE_Frame && (frame->state & State_Sunken)) { popupPal.setColor(QPalette::Midlight, frame->palette.background().color()); qDrawWinPanel(p, frame->rect, popupPal, frame->state & State_Sunken); @@ -1784,13 +1769,12 @@ case PE_FrameDockWidget: break; #endif // QT_NO_PROGRESSBAR - case PE_FrameTabWidget: - if (use2000style) { - QRect rect = opt->rect; - QPalette pal = opt->palette; - qDrawWinButton(p, opt->rect, opt->palette, false, 0); - break; - } + case PE_FrameTabWidget: { + QRect rect = opt->rect; + QPalette pal = opt->palette; + qDrawWinButton(p, opt->rect, opt->palette, false, 0); + break; + } default: QCommonStyle::drawPrimitive(pe, opt, p, w); } @@ -2066,10 +2050,6 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai p->setPen(light); p->drawLine(x1, y1 + 2, x1, y2 - ((onlyOne || firstTab) && selected && leftAligned ? 0 : borderThinkness)); p->drawPoint(x1 + 1, y1 + 1); - if (!use2000style) { - p->setPen(midlight); - p->drawLine(x1 + 1, y1 + 2, x1 + 1, y2 - ((onlyOne || firstTab) && selected && leftAligned ? 0 : borderThinkness)); - } } // Top { @@ -2077,10 +2057,6 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai int end = x2 - (nextSelected ? 0 : 2); p->setPen(light); p->drawLine(beg, y1, end, y1); - if (!use2000style) { - p->setPen(midlight); - p->drawLine(beg, y1 + 1, end, y1 + 1); - } } // Right if (lastTab || selected || onlyOne || !nextSelected) { @@ -2110,10 +2086,6 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai p->setPen(light); p->drawLine(x1, y2 - 2, x1, y1 + ((onlyOne || firstTab) && selected && leftAligned ? 0 : borderThinkness)); p->drawPoint(x1 + 1, y2 - 1); - if (!use2000style) { - p->setPen(midlight); - p->drawLine(x1 + 1, y2 - 2, x1 + 1, y1 + ((onlyOne || firstTab) && selected && leftAligned ? 0 : borderThinkness)); - } } // Bottom { @@ -2152,10 +2124,6 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai p->setPen(light); p->drawLine(x1 + 2, y1, x2 - ((onlyOne || firstTab) && selected && leftAligned ? 0 : borderThinkness), y1); p->drawPoint(x1 + 1, y1 + 1); - if (!use2000style) { - p->setPen(midlight); - p->drawLine(x1 + 2, y1 + 1, x2 - ((onlyOne || firstTab) && selected && leftAligned ? 0 : borderThinkness), y1 + 1); - } } // Left { @@ -2163,10 +2131,6 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai int end = y2 - (nextSelected ? 0 : 2); p->setPen(light); p->drawLine(x1, beg, x1, end); - if (!use2000style) { - p->setPen(midlight); - p->drawLine(x1 + 1, beg, x1 + 1, end); - } } // Bottom if (lastTab || selected || onlyOne || !nextSelected) { @@ -2198,11 +2162,6 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai p->setPen(light); p->drawLine(x2 - 2, y1, x1 + ((onlyOne || firstTab) && selected && leftAligned ? 0 : borderThinkness), y1); p->drawPoint(x2 - 1, y1 + 1); - if (!use2000style) { - p->setPen(midlight); - p->drawLine(x2 - 3, y1 + 1, x1 + ((onlyOne || firstTab) && selected && leftAligned ? 0 : borderThinkness), y1 + 1); - p->drawPoint(x2 - 1, y1); - } } // Right { @@ -2239,7 +2198,7 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai #ifndef QT_NO_SCROLLBAR case CE_ScrollBarSubLine: case CE_ScrollBarAddLine: { - if (use2000style && (opt->state & State_Sunken)) { + if ((opt->state & State_Sunken)) { p->setPen(opt->palette.dark().color()); p->setBrush(opt->palette.brush(QPalette::Button)); p->drawRect(opt->rect.adjusted(0, 0, -1, -1)); @@ -3027,8 +2986,7 @@ void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComp if ((cmb->subControls & SC_ComboBoxFrame)) { if (cmb->frame) { QPalette shadePal = opt->palette; - if (use2000style) - shadePal.setColor(QPalette::Midlight, shadePal.button().color()); + shadePal.setColor(QPalette::Midlight, shadePal.button().color()); qDrawWinPanel(p, opt->rect, shadePal, true, &editBrush); } else { @@ -3104,8 +3062,7 @@ void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComp QBrush editBrush = sb->palette.brush(QPalette::Base); QRect r = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxFrame, widget); QPalette shadePal = sb->palette; - if (use2000style) - shadePal.setColor(QPalette::Midlight, shadePal.button().color()); + shadePal.setColor(QPalette::Midlight, shadePal.button().color()); qDrawWinPanel(p, r, shadePal, true, &editBrush); } @@ -3234,7 +3191,7 @@ QSize QWindowsStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, + 2 * windowsItemFrame)); } int maxpmw = mi->maxIconWidth; - int tabSpacing = use2000style ? 20 :windowsTabSpacing; + int tabSpacing = 20; if (mi->text.contains(QLatin1Char('\t'))) w += tabSpacing; else if (mi->menuItemType == QStyleOptionMenuItem::SubMenu) diff --git a/src/gui/styles/qwindowsvistastyle.cpp b/src/gui/styles/qwindowsvistastyle.cpp index b131d39..3e65eef 100644 --- a/src/gui/styles/qwindowsvistastyle.cpp +++ b/src/gui/styles/qwindowsvistastyle.cpp @@ -2571,9 +2571,7 @@ void QWindowsVistaStylePrivate::startAnimation(Animation *t) bool QWindowsVistaStylePrivate::transitionsEnabled() const { BOOL animEnabled = false; - if (QT_WA_INLINE(SystemParametersInfo(SPI_GETCLIENTAREAANIMATION, 0, &animEnabled, 0), - SystemParametersInfoA(SPI_GETCLIENTAREAANIMATION, 0, &animEnabled, 0) - )) + if (SystemParametersInfo(SPI_GETCLIENTAREAANIMATION, 0, &animEnabled, 0)) { if (animEnabled) return true; diff --git a/src/gui/styles/qwindowsxpstyle.cpp b/src/gui/styles/qwindowsxpstyle.cpp index 322bfac..9c4afee 100644 --- a/src/gui/styles/qwindowsxpstyle.cpp +++ b/src/gui/styles/qwindowsxpstyle.cpp @@ -161,8 +161,7 @@ HTHEME XPThemeData::handle() htheme = QWindowsXPStylePrivate::handleMap->operator[](name); if (!htheme) { - htheme = pOpenThemeData(QWindowsXPStylePrivate::winId(widget), - (TCHAR*)name.utf16()); + htheme = pOpenThemeData(QWindowsXPStylePrivate::winId(widget), (wchar_t*)name.utf16()); if (htheme) { if (!QWindowsXPStylePrivate::handleMap) QWindowsXPStylePrivate::handleMap = new QMap; @@ -1547,11 +1546,11 @@ case PE_Frame: if (widget) { bool useGradient = true; const int maxlength = 256; - WCHAR themeFileName[maxlength]; - WCHAR themeColor[maxlength]; + wchar_t themeFileName[maxlength]; + wchar_t themeColor[maxlength]; // Due to a a scaling issue with the XP Silver theme, tab gradients are not used with it if (pGetCurrentThemeName(themeFileName, maxlength, themeColor, maxlength, NULL, 0) == S_OK) { - WCHAR* offset; + wchar_t *offset = 0; if ((offset = wcsrchr(themeFileName, QChar(QLatin1Char('\\')).unicode())) != NULL) { offset++; if (!lstrcmp(offset, L"Luna.msstyles") && !lstrcmp(offset, L"Metallic")) { diff --git a/src/gui/text/qfont_win.cpp b/src/gui/text/qfont_win.cpp index 2c27c9b..2293973 100644 --- a/src/gui/text/qfont_win.cpp +++ b/src/gui/text/qfont_win.cpp @@ -39,11 +39,6 @@ ** ****************************************************************************/ -// the miscrosoft platform SDK says that the Unicode versions of -// TextOut and GetTextExtentsPoint32 are supported on all platforms, so we use them -// exclusively to simplify code, save a lot of conversions into the local encoding -// and have generally better unicode support :) - #include "qfont.h" #include "qfont_p.h" #include "qfontengine_p.h" @@ -67,8 +62,7 @@ extern HDC shared_dc(); // common dc for all fonts // ### maybe move to qapplication_win QFont qt_LOGFONTtoQFont(LOGFONT& lf, bool /*scale*/) { - QString family = QT_WA_INLINE(QString::fromUtf16((ushort*)lf.lfFaceName), - QString::fromLocal8Bit((char*)lf.lfFaceName)); + QString family = QString::fromWCharArray(lf.lfFaceName); QFont qf(family); qf.setItalic(lf.lfItalic); if (lf.lfWeight != FW_DONTCARE) { diff --git a/src/gui/text/qfontdatabase_win.cpp b/src/gui/text/qfontdatabase_win.cpp index 2c0223b..2e8e5e4 100644 --- a/src/gui/text/qfontdatabase_win.cpp +++ b/src/gui/text/qfontdatabase_win.cpp @@ -195,21 +195,12 @@ static QString getEnglishName(const QString &familyName) QString i18n_name; HDC hdc = GetDC( 0 ); - HFONT hfont; - QT_WA( { - LOGFONTW lf; - memset( &lf, 0, sizeof( LOGFONTW ) ); - memcpy( lf.lfFaceName, familyName.utf16(), qMin(LF_FACESIZE, familyName.length())*sizeof(QChar) ); - lf.lfCharSet = DEFAULT_CHARSET; - hfont = CreateFontIndirectW( &lf ); - }, { - LOGFONTA lf; - memset( &lf, 0, sizeof( LOGFONTA ) ); - QByteArray lfam = familyName.toLocal8Bit(); - memcpy( lf.lfFaceName, lfam, qMin(LF_FACESIZE, lfam.size()) ); - lf.lfCharSet = DEFAULT_CHARSET; - hfont = CreateFontIndirectA( &lf ); - } ); + LOGFONT lf; + memset(&lf, 0, sizeof(LOGFONT)); + memcpy(lf.lfFaceName, familyName.utf16(), qMin(LF_FACESIZE, familyName.length()) * sizeof(wchar_t)); + lf.lfCharSet = DEFAULT_CHARSET; + HFONT hfont = CreateFontIndirect(&lf); + if(!hfont) { ReleaseDC(0, hdc); return QString(); @@ -245,32 +236,6 @@ error: return i18n_name; } -static void getFontSignature(const QString &familyName, - NEWTEXTMETRICEX *textmetric, - FONTSIGNATURE *signature) -{ - QT_WA({ - Q_UNUSED(familyName); - *signature = textmetric->ntmFontSig; - }, { - // the textmetric structure we get from EnumFontFamiliesEx on Win9x has - // a FONTSIGNATURE, but that one is uninitialized and doesn't work. Have to go - // the hard way and load the font to find out. - HDC hdc = GetDC(0); - LOGFONTA lf; - memset(&lf, 0, sizeof(LOGFONTA)); - QByteArray lfam = familyName.toLocal8Bit(); - memcpy(lf.lfFaceName, lfam.data(), qMin(LF_FACESIZE, lfam.length())); - lf.lfCharSet = DEFAULT_CHARSET; - HFONT hfont = CreateFontIndirectA(&lf); - HGDIOBJ oldobj = SelectObject(hdc, hfont); - GetTextCharsetInfo(hdc, signature, 0); - SelectObject(hdc, oldobj); - DeleteObject(hfont); - ReleaseDC(0, hdc); - }); -} - static void addFontToDatabase(QString familyName, const QString &scriptName, TEXTMETRIC *textmetric, @@ -288,26 +253,17 @@ void addFontToDatabase(QString familyName, const QString &scriptName, bool scalable; int size; -// QString escript = QString::fromUtf16((ushort *)f->elfScript); +// QString escript = QString::fromWCharArray(f->elfScript); // qDebug("script=%s", escript.latin1()); - QT_WA({ - NEWTEXTMETRIC *tm = (NEWTEXTMETRIC *)textmetric; - fixed = !(tm->tmPitchAndFamily & TMPF_FIXED_PITCH); - ttf = (tm->tmPitchAndFamily & TMPF_TRUETYPE); - scalable = tm->tmPitchAndFamily & (TMPF_VECTOR|TMPF_TRUETYPE); - size = scalable ? SMOOTH_SCALABLE : tm->tmHeight; - italic = tm->tmItalic; - weight = tm->tmWeight; - } , { - NEWTEXTMETRICA *tm = (NEWTEXTMETRICA *)textmetric; - fixed = !(tm->tmPitchAndFamily & TMPF_FIXED_PITCH); - ttf = (tm->tmPitchAndFamily & TMPF_TRUETYPE); - scalable = tm->tmPitchAndFamily & (TMPF_VECTOR|TMPF_TRUETYPE); - size = scalable ? SMOOTH_SCALABLE : tm->tmHeight; - italic = tm->tmItalic; - weight = tm->tmWeight; - }); + NEWTEXTMETRIC *tm = (NEWTEXTMETRIC *)textmetric; + fixed = !(tm->tmPitchAndFamily & TMPF_FIXED_PITCH); + ttf = (tm->tmPitchAndFamily & TMPF_TRUETYPE); + scalable = tm->tmPitchAndFamily & (TMPF_VECTOR|TMPF_TRUETYPE); + size = scalable ? SMOOTH_SCALABLE : tm->tmHeight; + italic = tm->tmItalic; + weight = tm->tmWeight; + // the "@family" fonts are just the same as "family". Ignore them. if (familyName[0] != QLatin1Char('@') && !familyName.startsWith(QLatin1String("WST_"))) { QtFontStyle::Key styleKey; @@ -420,18 +376,10 @@ static int CALLBACK storeFont(ENUMLOGFONTEX* f, NEWTEXTMETRICEX *textmetric, int type, LPARAM /*p*/) { - QString familyName; - QT_WA({ - familyName = QString::fromUtf16((ushort*)f->elfLogFont.lfFaceName); - },{ - ENUMLOGFONTEXA *fa = (ENUMLOGFONTEXA *)f; - familyName = QString::fromLocal8Bit(fa->elfLogFont.lfFaceName); - }); - QString script = QT_WA_INLINE(QString::fromUtf16((const ushort *)f->elfScript), - QString::fromLocal8Bit((const char *)((ENUMLOGFONTEXA *)f)->elfScript)); - - FONTSIGNATURE signature; - getFontSignature(familyName, textmetric, &signature); + QString familyName = QString::fromWCharArray(f->elfLogFont.lfFaceName); + QString script = QString::fromWCharArray(f->elfScript); + + FONTSIGNATURE signature = textmetric->ntmFontSig; // NEWTEXTMETRICEX is a NEWTEXTMETRIC, which according to the documentation is // identical to a TEXTMETRIC except for the last four members, which we don't use @@ -459,33 +407,17 @@ void populate_database(const QString& fam) HDC dummy = GetDC(0); - QT_WA({ - LOGFONT lf; - lf.lfCharSet = DEFAULT_CHARSET; - if (fam.isNull()) { - lf.lfFaceName[0] = 0; - } else { - memcpy(lf.lfFaceName, fam.utf16(), sizeof(TCHAR)*qMin(fam.length()+1,32)); // 32 = Windows hard-coded - } - lf.lfPitchAndFamily = 0; - - EnumFontFamiliesEx(dummy, &lf, - (FONTENUMPROC)storeFont, (LPARAM)privateDb(), 0); - } , { - LOGFONTA lf; - lf.lfCharSet = DEFAULT_CHARSET; - if (fam.isNull()) { - lf.lfFaceName[0] = 0; - } else { - QByteArray lname = fam.toLocal8Bit(); - memcpy(lf.lfFaceName,lname.data(), - qMin(lname.length()+1,32)); // 32 = Windows hard-coded - } - lf.lfPitchAndFamily = 0; + LOGFONT lf; + lf.lfCharSet = DEFAULT_CHARSET; + if (fam.isNull()) { + lf.lfFaceName[0] = 0; + } else { + memcpy(lf.lfFaceName, fam.utf16(), sizeof(wchar_t) * qMin(fam.length() + 1, 32)); // 32 = Windows hard-coded + } + lf.lfPitchAndFamily = 0; - EnumFontFamiliesExA(dummy, &lf, - (FONTENUMPROCA)storeFont, (LPARAM)privateDb(), 0); - }); + EnumFontFamiliesEx(dummy, &lf, + (FONTENUMPROC)storeFont, (LPARAM)privateDb(), 0); ReleaseDC(0, dummy); @@ -496,21 +428,11 @@ void populate_database(const QString& fam) for (int j = 0; j < fnt.families.count(); ++j) { const QString familyName = fnt.families.at(j); HDC hdc = GetDC(0); - HFONT hfont; - QT_WA({ - LOGFONTW lf; - memset(&lf, 0, sizeof(LOGFONTW)); - memcpy(lf.lfFaceName, familyName.utf16(), qMin(LF_FACESIZE, familyName.size())); - lf.lfCharSet = DEFAULT_CHARSET; - hfont = CreateFontIndirectW(&lf); - } , { - LOGFONTA lf; - memset(&lf, 0, sizeof(LOGFONTA)); - QByteArray lfam = familyName.toLocal8Bit(); - memcpy(lf.lfFaceName, lfam.data(), qMin(LF_FACESIZE, lfam.length())); - lf.lfCharSet = DEFAULT_CHARSET; - hfont = CreateFontIndirectA(&lf); - }); + LOGFONT lf; + memset(&lf, 0, sizeof(LOGFONT)); + memcpy(lf.lfFaceName, familyName.utf16(), sizeof(wchar_t) * qMin(LF_FACESIZE, familyName.size())); + lf.lfCharSet = DEFAULT_CHARSET; + HFONT hfont = CreateFontIndirect(&lf); HGDIOBJ oldobj = SelectObject(hdc, hfont); TEXTMETRIC textMetrics; @@ -598,17 +520,10 @@ static void initFontInfo(QFontEngineWin *fe, const QFontDef &request, const QFon HDC dc = ((request.styleStrategy & QFont::PreferDevice) && fp->hdc) ? fp->hdc : shared_dc(); SelectObject(dc, fe->hfont); - QT_WA({ - TCHAR n[64]; - GetTextFaceW(dc, 64, n); - fe->fontDef.family = QString::fromUtf16((ushort*)n); - fe->fontDef.fixedPitch = !(fe->tm.w.tmPitchAndFamily & TMPF_FIXED_PITCH); - } , { - char an[64]; - GetTextFaceA(dc, 64, an); - fe->fontDef.family = QString::fromLocal8Bit(an); - fe->fontDef.fixedPitch = !(fe->tm.a.tmPitchAndFamily & TMPF_FIXED_PITCH); - }); + wchar_t n[64]; + GetTextFace(dc, 64, n); + fe->fontDef.family = QString::fromWCharArray(n); + fe->fontDef.fixedPitch = !(fe->tm.tmPitchAndFamily & TMPF_FIXED_PITCH); if (fe->fontDef.pointSize < 0) { fe->fontDef.pointSize = fe->fontDef.pixelSize * 72. / fp->dpi; } else if (fe->fontDef.pixelSize == -1) { @@ -704,12 +619,7 @@ QFontEngine *loadEngine(int script, const QFontPrivate *fp, const QFontDef &requ HFONT hfont = 0; if (fp->rawMode) { // will choose a stock font - int f, deffnt; - // ### why different? - if ((QSysInfo::WindowsVersion & QSysInfo::WV_NT_based) || QSysInfo::WindowsVersion == QSysInfo::WV_32s) - deffnt = SYSTEM_FONT; - else - deffnt = DEFAULT_GUI_FONT; + int f, deffnt = SYSTEM_FONT; QString fam = desc->family->name.toLower(); if (fam == QLatin1String("default")) f = deffnt; @@ -778,11 +688,7 @@ QFontEngine *loadEngine(int script, const QFontPrivate *fp, const QFontDef &requ } else if (request.styleStrategy & QFont::PreferDevice) { strat = OUT_DEVICE_PRECIS; } else if (request.styleStrategy & QFont::PreferOutline) { - QT_WA({ - strat = OUT_OUTLINE_PRECIS; - } , { - strat = OUT_TT_PRECIS; - }); + strat = OUT_OUTLINE_PRECIS; } else if (request.styleStrategy & QFont::ForceOutline) { strat = OUT_TT_ONLY_PRECIS; #endif @@ -801,7 +707,7 @@ QFontEngine *loadEngine(int script, const QFontPrivate *fp, const QFontDef &requ if (request.styleStrategy & QFont::PreferAntialias) { if (QSysInfo::WindowsVersion >= QSysInfo::WV_XP) { - qual = 5; // == CLEARTYPE_QUALITY; + qual = CLEARTYPE_QUALITY; preferClearTypeAA = true; } else { qual = ANTIALIASED_QUALITY; @@ -827,16 +733,8 @@ QFontEngine *loadEngine(int script, const QFontPrivate *fp, const QFontDef &requ if (fam == QLatin1String("Courier") && !(request.styleStrategy & QFont::PreferBitmap)) fam = QLatin1String("Courier New"); - QT_WA({ - memcpy(lf.lfFaceName, fam.utf16(), sizeof(TCHAR)*qMin(fam.length()+1,32)); // 32 = Windows hard-coded - hfont = CreateFontIndirect(&lf); - } , { - // LOGFONTA and LOGFONTW are binary compatible - QByteArray lname = fam.toLocal8Bit(); - memcpy(lf.lfFaceName,lname.data(), - qMin(lname.length()+1,32)); // 32 = Windows hard-coded - hfont = CreateFontIndirectA((LOGFONTA*)&lf); - }); + memcpy(lf.lfFaceName, fam.utf16(), sizeof(wchar_t) * qMin(fam.length() + 1, 32)); // 32 = Windows hard-coded + hfont = CreateFontIndirect(&lf); if (!hfont) qErrnoWarning("QFontEngine::loadEngine: CreateFontIndirect failed"); @@ -845,17 +743,12 @@ QFontEngine *loadEngine(int script, const QFontPrivate *fp, const QFontDef &requ int avWidth = 0; BOOL res; HGDIOBJ oldObj = SelectObject(hdc, hfont); - QT_WA({ - TEXTMETRICW tm; - res = GetTextMetricsW(hdc, &tm); - avWidth = tm.tmAveCharWidth; - ttf = tm.tmPitchAndFamily & TMPF_TRUETYPE; - } , { - TEXTMETRICA tm; - res = GetTextMetricsA(hdc, &tm); - avWidth = tm.tmAveCharWidth; - ttf = tm.tmPitchAndFamily & TMPF_TRUETYPE; - }); + + TEXTMETRIC tm; + res = GetTextMetrics(hdc, &tm); + avWidth = tm.tmAveCharWidth; + ttf = tm.tmPitchAndFamily & TMPF_TRUETYPE; + SelectObject(hdc, oldObj); if (hfont && (!ttf || request.stretch != 100)) { @@ -863,11 +756,7 @@ QFontEngine *loadEngine(int script, const QFontPrivate *fp, const QFontDef &requ if (!res) qErrnoWarning("QFontEngine::loadEngine: GetTextMetrics failed"); lf.lfWidth = avWidth * request.stretch/100; - QT_WA({ - hfont = CreateFontIndirect(&lf); - } , { - hfont = CreateFontIndirectA((LOGFONTA*)&lf); - }); + hfont = CreateFontIndirect(&lf); if (!hfont) qErrnoWarning("QFontEngine::loadEngine: CreateFontIndirect with stretch failed"); } @@ -969,12 +858,6 @@ static QFontEngine *loadWin(const QFontPrivate *d, int script, const QFontDef &r // list of families to try QStringList family_list = familyList(req); - if(QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based && req.family.toLower() == QLatin1String("ms sans serif")) { - // small hack for Dos based machines to get the right font for non - // latin text when using the default font. - family_list << QLatin1String("Arial"); - } - const char *stylehint = styleHint(d->request); if (stylehint) family_list << QLatin1String(stylehint); @@ -1165,21 +1048,21 @@ static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt) HANDLE handle = 0; { -#ifdef QT_NO_TEMPORARYFILE - TCHAR lpBuffer[MAX_PATH]; +#ifdef QT_NO_TEMPORARYFILE + wchar_t lpBuffer[MAX_PATH]; GetTempPath(MAX_PATH, lpBuffer); - QString s = QString::fromUtf16((const ushort *) lpBuffer); + QString s = QString::fromWCharArray(lpBuffer); QFile tempfile(s + QLatin1String("/font") + QString::number(GetTickCount()) + QLatin1String(".ttf")); if (!tempfile.open(QIODevice::ReadWrite)) #else QTemporaryFile tempfile(QLatin1String("XXXXXXXX.ttf")); if (!tempfile.open()) -#endif +#endif // QT_NO_TEMPORARYFILE return; if (tempfile.write(fnt->data) == -1) return; -#ifndef QT_NO_TEMPORARYFILE +#ifndef QT_NO_TEMPORARYFILE tempfile.setAutoRemove(false); #endif fnt->fileName = QFileInfo(tempfile.fileName()).absoluteFilePath(); @@ -1191,13 +1074,11 @@ static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt) } #else DWORD dummy = 0; - HANDLE handle = ptrAddFontMemResourceEx((void *)fnt->data.constData(), - fnt->data.size(), - 0, - &dummy); + HANDLE handle = ptrAddFontMemResourceEx((void *)fnt->data.constData(), fnt->data.size(), 0, + &dummy); if (handle == 0) return; -#endif +#endif // Q_OS_WINCE fnt->handle = handle; fnt->data = QByteArray(); @@ -1219,12 +1100,10 @@ static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt) // supported from 2000 on, so no need to deal with the *A variant PtrAddFontResourceExW ptrAddFontResourceExW = (PtrAddFontResourceExW)QLibrary::resolve(QLatin1String("gdi32"), "AddFontResourceExW"); - if (!ptrAddFontResourceExW) + if (!ptrAddFontResourceExW + || ptrAddFontResourceExW((wchar_t*)fnt->fileName.utf16(), FR_PRIVATE, 0) == 0) return; - - if (ptrAddFontResourceExW((LPCWSTR)fnt->fileName.utf16(), FR_PRIVATE, 0) == 0) - return; -#endif +#endif // Q_OS_WINCE fnt->memoryFont = false; } @@ -1250,12 +1129,10 @@ bool QFontDatabase::removeApplicationFont(int handle) #else PtrRemoveFontMemResourceEx ptrRemoveFontMemResourceEx = (PtrRemoveFontMemResourceEx)QLibrary::resolve(QLatin1String("gdi32"), "RemoveFontMemResourceEx"); - if (!ptrRemoveFontMemResourceEx) - return false; - - if (!ptrRemoveFontMemResourceEx(font.handle)) + if (!ptrRemoveFontMemResourceEx + || !ptrRemoveFontMemResourceEx(font.handle)) return false; -#endif +#endif // Q_OS_WINCE } else { #ifdef Q_OS_WINCE if (!RemoveFontResource((LPCWSTR)font.fileName.utf16())) @@ -1263,12 +1140,10 @@ bool QFontDatabase::removeApplicationFont(int handle) #else PtrRemoveFontResourceExW ptrRemoveFontResourceExW = (PtrRemoveFontResourceExW)QLibrary::resolve(QLatin1String("gdi32"), "RemoveFontResourceExW"); - if (!ptrRemoveFontResourceExW) - return false; - - if (!ptrRemoveFontResourceExW((LPCWSTR)font.fileName.utf16(), FR_PRIVATE, 0)) + if (!ptrRemoveFontResourceExW + || !ptrRemoveFontResourceExW((LPCWSTR)font.fileName.utf16(), FR_PRIVATE, 0)) return false; -#endif +#endif // Q_OS_WINCE } db->invalidate(); diff --git a/src/gui/text/qfontengine_win.cpp b/src/gui/text/qfontengine_win.cpp index 9715aef..f4adc9a 100644 --- a/src/gui/text/qfontengine_win.cpp +++ b/src/gui/text/qfontengine_win.cpp @@ -48,7 +48,6 @@ #include #include #include -#include #include #include @@ -85,8 +84,6 @@ ((quint32)(ch1)) \ ) -typedef BOOL (WINAPI *PtrGetCharWidthI)(HDC, UINT, UINT, LPWORD, LPINT); - // common DC for all fonts QT_BEGIN_NAMESPACE @@ -130,6 +127,7 @@ HDC shared_dc() static HFONT stock_sysfont = 0; +typedef BOOL (WINAPI *PtrGetCharWidthI)(HDC, UINT, UINT, LPWORD, LPINT); static PtrGetCharWidthI ptrGetCharWidthI = 0; static bool resolvedGetCharWidthI = false; @@ -141,27 +139,6 @@ static void resolveGetCharWidthI() ptrGetCharWidthI = (PtrGetCharWidthI)QLibrary::resolve(QLatin1String("gdi32"), "GetCharWidthI"); } -// Copy a LOGFONTW struct into a LOGFONTA by converting the face name to an 8 bit value. -// This is needed when calling CreateFontIndirect on non-unicode windowses. -inline static void wa_copy_logfont(LOGFONTW *lfw, LOGFONTA *lfa) -{ - lfa->lfHeight = lfw->lfHeight; - lfa->lfWidth = lfw->lfWidth; - lfa->lfEscapement = lfw->lfEscapement; - lfa->lfOrientation = lfw->lfOrientation; - lfa->lfWeight = lfw->lfWeight; - lfa->lfItalic = lfw->lfItalic; - lfa->lfUnderline = lfw->lfUnderline; - lfa->lfCharSet = lfw->lfCharSet; - lfa->lfOutPrecision = lfw->lfOutPrecision; - lfa->lfClipPrecision = lfw->lfClipPrecision; - lfa->lfQuality = lfw->lfQuality; - lfa->lfPitchAndFamily = lfw->lfPitchAndFamily; - - QString fam = QString::fromUtf16((const ushort*)lfw->lfFaceName); - memcpy(lfa->lfFaceName, fam.toLocal8Bit().constData(), fam.length() + 1); -} - // defined in qtextengine_win.cpp typedef void *SCRIPT_CACHE; typedef HRESULT (WINAPI *fScriptFreeCache)(SCRIPT_CACHE *); @@ -187,14 +164,6 @@ static inline quint16 getUShort(unsigned char *p) return val; } -static inline HFONT systemFont() -{ - if (stock_sysfont == 0) - stock_sysfont = (HFONT)GetStockObject(SYSTEM_FONT); - return stock_sysfont; -} - - // general font engine QFixed QFontEngineWin::lineThickness() const @@ -205,33 +174,18 @@ QFixed QFontEngineWin::lineThickness() const return QFontEngine::lineThickness(); } -#if defined(Q_WS_WINCE) -static OUTLINETEXTMETRICW *getOutlineTextMetric(HDC hdc) +static OUTLINETEXTMETRIC *getOutlineTextMetric(HDC hdc) { int size; - size = GetOutlineTextMetricsW(hdc, 0, 0); - OUTLINETEXTMETRICW *otm = (OUTLINETEXTMETRICW *)malloc(size); - GetOutlineTextMetricsW(hdc, size, otm); + size = GetOutlineTextMetrics(hdc, 0, 0); + OUTLINETEXTMETRIC *otm = (OUTLINETEXTMETRIC *)malloc(size); + GetOutlineTextMetrics(hdc, size, otm); return otm; } -#else -static OUTLINETEXTMETRICA *getOutlineTextMetric(HDC hdc) -{ - int size; - size = GetOutlineTextMetricsA(hdc, 0, 0); - OUTLINETEXTMETRICA *otm = (OUTLINETEXTMETRICA *)malloc(size); - GetOutlineTextMetricsA(hdc, size, otm); - return otm; -} -#endif void QFontEngineWin::getCMap() { - QT_WA({ - ttf = (bool)(tm.w.tmPitchAndFamily & TMPF_TRUETYPE); - } , { - ttf = (bool)(tm.a.tmPitchAndFamily & TMPF_TRUETYPE); - }); + ttf = (bool)(tm.tmPitchAndFamily & TMPF_TRUETYPE); HDC hdc = shared_dc(); SelectObject(hdc, hfont); bool symb = false; @@ -249,11 +203,7 @@ void QFontEngineWin::getCMap() designToDevice = 1; _faceId.index = 0; if(cmap) { -#if defined(Q_WS_WINCE) - OUTLINETEXTMETRICW *otm = getOutlineTextMetric(hdc); -#else - OUTLINETEXTMETRICA *otm = getOutlineTextMetric(hdc); -#endif + OUTLINETEXTMETRIC *otm = getOutlineTextMetric(hdc); designToDevice = QFixed((int)otm->otmEMSquare)/int(otm->otmTextMetrics.tmHeight); unitsPerEm = otm->otmEMSquare; x_height = (int)otm->otmsXHeight; @@ -263,7 +213,7 @@ void QFontEngineWin::getCMap() fsType = otm->otmfsType; free(otm); } else { - unitsPerEm = tm.w.tmHeight; + unitsPerEm = tm.tmHeight; } } @@ -303,19 +253,14 @@ int QFontEngineWin::getGlyphIndexes(const QChar *str, int numChars, QGlyphLayout } } else { #endif - ushort first, last; - QT_WA({ - first = tm.w.tmFirstChar; - last = tm.w.tmLastChar; - }, { - first = tm.a.tmFirstChar; - last = tm.a.tmLastChar; - }); + wchar_t first = tm.tmFirstChar; + wchar_t last = tm.tmLastChar; + for (; i < numChars; ++i, ++glyph_pos) { uint ucs = QChar::mirroredChar(getChar(str, i, numChars)); if ( #ifdef Q_WS_WINCE - tm.w.tmFirstChar > 60000 || // see line 375 + tm.tmFirstChar > 60000 || // see line 375 #endif ucs >= first && ucs <= last) glyphs->glyphs[glyph_pos] = ucs; @@ -341,19 +286,14 @@ int QFontEngineWin::getGlyphIndexes(const QChar *str, int numChars, QGlyphLayout } } else { #endif - ushort first, last; - QT_WA({ - first = tm.w.tmFirstChar; - last = tm.w.tmLastChar; - }, { - first = tm.a.tmFirstChar; - last = tm.a.tmLastChar; - }); + wchar_t first = tm.tmFirstChar; + wchar_t last = tm.tmLastChar; + for (; i < numChars; ++i, ++glyph_pos) { uint uc = getChar(str, i, numChars); if ( #ifdef Q_WS_WINCE - tm.w.tmFirstChar > 60000 || // see comment in QFontEngineWin + tm.tmFirstChar > 60000 || // see comment in QFontEngineWin #endif uc >= first && uc <= last) glyphs->glyphs[glyph_pos] = uc; @@ -387,28 +327,14 @@ QFontEngineWin::QFontEngineWin(const QString &name, HFONT _hfont, bool stockFont lineWidth = -1; x_height = -1; - BOOL res; - QT_WA({ - res = GetTextMetricsW(hdc, &tm.w); - } , { - res = GetTextMetricsA(hdc, &tm.a); - }); - fontDef.fixedPitch = !(tm.w.tmPitchAndFamily & TMPF_FIXED_PITCH); + BOOL res = GetTextMetrics(hdc, &tm); + fontDef.fixedPitch = !(tm.tmPitchAndFamily & TMPF_FIXED_PITCH); if (!res) qErrnoWarning("QFontEngineWin: GetTextMetrics failed"); - cache_cost = tm.w.tmHeight * tm.w.tmAveCharWidth * 2000; + cache_cost = tm.tmHeight * tm.tmAveCharWidth * 2000; getCMap(); - useTextOutA = false; -#ifndef Q_OS_WINCE - // TextOutW doesn't work for symbol fonts on Windows 95! - // since we're using glyph indices we don't care for ttfs about this! - if (QSysInfo::WindowsVersion == QSysInfo::WV_95 && !ttf && - (_name == QLatin1String("Marlett") || _name == QLatin1String("Symbol") || - _name == QLatin1String("Webdings") || _name == QLatin1String("Wingdings"))) - useTextOutA = true; -#endif widthCache = 0; widthCacheSize = 0; designAdvances = 0; @@ -427,7 +353,7 @@ QFontEngineWin::~QFontEngineWin() free(widthCache); // make sure we aren't by accident still selected - SelectObject(shared_dc(), systemFont()); + SelectObject(shared_dc(), (HFONT)GetStockObject(SYSTEM_FONT)); if (!stockFont) { if (!DeleteObject(hfont)) @@ -435,39 +361,12 @@ QFontEngineWin::~QFontEngineWin() } } -HGDIOBJ QFontEngineWin::selectDesignFont(QFixed *overhang) const +HGDIOBJ QFontEngineWin::selectDesignFont() const { LOGFONT f = logfont; f.lfHeight = unitsPerEm; - HFONT designFont; - QT_WA({ - designFont = CreateFontIndirectW(&f); - }, { - LOGFONTA fa; - wa_copy_logfont(&f, &fa); - designFont = CreateFontIndirectA(&fa); - }); - HGDIOBJ oldFont = SelectObject(shared_dc(), designFont); - - if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) { - BOOL res; - QT_WA({ - TEXTMETRICW tm; - res = GetTextMetricsW(shared_dc(), &tm); - if (!res) - qErrnoWarning("QFontEngineWin: GetTextMetrics failed"); - *overhang = QFixed((int)tm.tmOverhang) / designToDevice; - } , { - TEXTMETRICA tm; - res = GetTextMetricsA(shared_dc(), &tm); - if (!res) - qErrnoWarning("QFontEngineWin: GetTextMetrics failed"); - *overhang = QFixed((int)tm.tmOverhang) / designToDevice; - }); - } else { - *overhang = 0; - } - return oldFont; + HFONT designFont = CreateFontIndirect(&f); + return SelectObject(shared_dc(), designFont); } bool QFontEngineWin::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const @@ -486,8 +385,6 @@ bool QFontEngineWin::stringToCMap(const QChar *str, int len, QGlyphLayout *glyph HDC hdc = shared_dc(); if (flags & QTextEngine::DesignMetrics) { HGDIOBJ oldFont = 0; - QFixed overhang = 0; - int glyph_pos = 0; for(register int i = 0; i < len; i++) { bool surrogate = (str[i].unicode() >= 0xd800 && str[i].unicode() < 0xdc00 && i < len-1 @@ -502,9 +399,9 @@ bool QFontEngineWin::stringToCMap(const QChar *str, int len, QGlyphLayout *glyph } if(designAdvances[glyph] < -999999) { if(!oldFont) - oldFont = selectDesignFont(&overhang); + oldFont = selectDesignFont(); SIZE size = {0, 0}; - GetTextExtentPoint32W(hdc, (wchar_t *)(str+i), surrogate ? 2 : 1, &size); + GetTextExtentPoint32(hdc, (wchar_t *)(str+i), surrogate ? 2 : 1, &size); designAdvances[glyph] = QFixed((int)size.cx)/designToDevice; } glyphs->advances_x[glyph_pos] = designAdvances[glyph]; @@ -538,7 +435,7 @@ bool QFontEngineWin::stringToCMap(const QChar *str, int len, QGlyphLayout *glyph SIZE size = {0, 0}; if (!oldFont) oldFont = SelectObject(hdc, hfont); - GetTextExtentPoint32W(hdc, (wchar_t *)str + i, surrogate ? 2 : 1, &size); + GetTextExtentPoint32(hdc, (wchar_t *)str + i, surrogate ? 2 : 1, &size); glyphs->advances_x[glyph_pos] = size.cx; // if glyph's within cache range, store it for later if (size.cx > 0 && size.cx < 0x100) @@ -564,8 +461,6 @@ void QFontEngineWin::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFla HGDIOBJ oldFont = 0; HDC hdc = shared_dc(); if (ttf && (flags & QTextEngine::DesignMetrics)) { - QFixed overhang = 0; - for(int i = 0; i < glyphs->numGlyphs; i++) { unsigned int glyph = glyphs->glyphs[i]; if(int(glyph) >= designAdvancesSize) { @@ -575,35 +470,14 @@ void QFontEngineWin::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFla designAdvances[i] = -1000000; designAdvancesSize = newSize; } - if(designAdvances[glyph] < -999999) { - if(!oldFont) - oldFont = selectDesignFont(&overhang); + if (designAdvances[glyph] < -999999) { + if (!oldFont) + oldFont = selectDesignFont(); - if (ptrGetCharWidthI) { - int width = 0; + int width = 0; + if (ptrGetCharWidthI) ptrGetCharWidthI(hdc, glyph, 1, 0, &width); - - designAdvances[glyph] = QFixed(width) / designToDevice; - } else { -#ifndef Q_WS_WINCE - GLYPHMETRICS gm; - DWORD res = GDI_ERROR; - MAT2 mat; - mat.eM11.value = mat.eM22.value = 1; - mat.eM11.fract = mat.eM22.fract = 0; - mat.eM21.value = mat.eM12.value = 0; - mat.eM21.fract = mat.eM12.fract = 0; - QT_WA({ - res = GetGlyphOutlineW(hdc, glyph, GGO_METRICS|GGO_GLYPH_INDEX|GGO_NATIVE, &gm, 0, 0, &mat); - } , { - res = GetGlyphOutlineA(hdc, glyph, GGO_METRICS|GGO_GLYPH_INDEX|GGO_NATIVE, &gm, 0, 0, &mat); - }); - - if (res != GDI_ERROR) { - designAdvances[glyph] = QFixed(gm.gmCellIncX) / designToDevice; - } -#endif - } + designAdvances[glyph] = QFixed(width) / designToDevice; } glyphs->advances_x[i] = designAdvances[glyph]; glyphs->advances_y[i] = 0; @@ -611,8 +485,6 @@ void QFontEngineWin::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFla if(oldFont) DeleteObject(SelectObject(hdc, oldFont)); } else { - int overhang = (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) ? tm.a.tmOverhang : 0; - for(int i = 0; i < glyphs->numGlyphs; i++) { unsigned int glyph = glyphs->glyphs[i]; @@ -640,31 +512,10 @@ void QFontEngineWin::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFla ++chrLen; } SIZE size = {0, 0}; - GetTextExtentPoint32W(hdc, (wchar_t *)ch, chrLen, &size); + GetTextExtentPoint32(hdc, (wchar_t *)ch, chrLen, &size); width = size.cx; } else if (ptrGetCharWidthI) { ptrGetCharWidthI(hdc, glyph, 1, 0, &width); - - width -= overhang; - } else { -#ifndef Q_WS_WINCE - GLYPHMETRICS gm; - DWORD res = GDI_ERROR; - MAT2 mat; - mat.eM11.value = mat.eM22.value = 1; - mat.eM11.fract = mat.eM22.fract = 0; - mat.eM21.value = mat.eM12.value = 0; - mat.eM21.fract = mat.eM12.fract = 0; - QT_WA({ - res = GetGlyphOutlineW(hdc, glyph, GGO_METRICS|GGO_GLYPH_INDEX, &gm, 0, 0, &mat); - } , { - res = GetGlyphOutlineA(hdc, glyph, GGO_METRICS|GGO_GLYPH_INDEX, &gm, 0, 0, &mat); - }); - - if (res != GDI_ERROR) { - width = gm.gmCellIncX; - } -#endif } glyphs->advances_x[i] = width; // if glyph's within cache range, store it for later @@ -687,7 +538,7 @@ glyph_metrics_t QFontEngineWin::boundingBox(const QGlyphLayout &glyphs) for (int i = 0; i < glyphs.numGlyphs; ++i) w += glyphs.effectiveAdvance(i); - return glyph_metrics_t(0, -tm.w.tmAscent, w, tm.w.tmHeight, w, 0); + return glyph_metrics_t(0, -tm.tmAscent, w, tm.tmHeight, w, 0); } @@ -705,30 +556,13 @@ glyph_metrics_t QFontEngineWin::boundingBox(glyph_t glyph, const QTransform &t) HDC hdc = shared_dc(); SelectObject(hdc, hfont); - if(!ttf) { - SIZE s = {0, 0}; - WCHAR ch = glyph; - int width; - int overhang = 0; - static bool resolved = false; - if (!resolved) { - QLibrary lib(QLatin1String("gdi32")); - qt_GetCharABCWidthsFloat = (pGetCharABCWidthsFloat) lib.resolve("GetCharABCWidthsFloatW"); - resolved = true; - } - if (QT_WA_INLINE(true, false) && qt_GetCharABCWidthsFloat) { - ABCFLOAT abc; - qt_GetCharABCWidthsFloat(hdc, ch, ch, &abc); - width = qRound(abc.abcfB); - } else { - GetTextExtentPoint32W(hdc, &ch, 1, &s); - overhang = (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) ? tm.a.tmOverhang : 0; - width = s.cx; - } + if (!ttf) { + wchar_t ch = glyph; + ABCFLOAT abc; + GetCharABCWidthsFloat(hdc, ch, ch, &abc); + int width = qRound(abc.abcfB); - return glyph_metrics_t(0, -tm.a.tmAscent, - width, tm.a.tmHeight, - width-overhang, 0).transformed(t); + return glyph_metrics_t(0, -tm.tmAscent, width, tm.tmHeight, width, 0).transformed(t); } else { DWORD res = 0; MAT2 mat; @@ -753,11 +587,8 @@ glyph_metrics_t QFontEngineWin::boundingBox(glyph_t glyph, const QTransform &t) SetWorldTransform(hdc, &xform); } - QT_WA({ - res = GetGlyphOutlineW(hdc, glyph, GGO_METRICS|GGO_GLYPH_INDEX, &gm, 0, 0, &mat); - } , { - res = GetGlyphOutlineA(hdc, glyph, GGO_METRICS|GGO_GLYPH_INDEX, &gm, 0, 0, &mat); - }); + res = GetGlyphOutline(hdc, glyph, GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, 0, &mat); + if (t.type() > QTransform::TxTranslate) { XFORM xform; xform.eM11 = xform.eM22 = 1; @@ -793,28 +624,28 @@ glyph_metrics_t QFontEngineWin::boundingBox(glyph_t glyph, const QTransform &t) else #endif { // fallback - width = tm.w.tmMaxCharWidth; + width = tm.tmMaxCharWidth; advance = width; } SelectObject(hdc, oldFont); - return glyph_metrics_t(0, -tm.w.tmAscent, width, tm.w.tmHeight, advance, 0).transformed(t); + return glyph_metrics_t(0, -tm.tmAscent, width, tm.tmHeight, advance, 0).transformed(t); #endif } QFixed QFontEngineWin::ascent() const { - return tm.w.tmAscent; + return tm.tmAscent; } QFixed QFontEngineWin::descent() const { - return tm.w.tmDescent; + return tm.tmDescent; } QFixed QFontEngineWin::leading() const { - return tm.w.tmExternalLeading; + return tm.tmExternalLeading; } @@ -827,12 +658,12 @@ QFixed QFontEngineWin::xHeight() const QFixed QFontEngineWin::averageCharWidth() const { - return tm.w.tmAveCharWidth; + return tm.tmAveCharWidth; } qreal QFontEngineWin::maxCharWidth() const { - return tm.w.tmMaxCharWidth; + return tm.tmMaxCharWidth; } enum { max_font_count = 256 }; @@ -879,10 +710,10 @@ qreal QFontEngineWin::minRightBearing() const SelectObject(hdc, hfont); if (ttf) { ABC *abc = 0; - int n = QT_WA_INLINE(tm.w.tmLastChar - tm.w.tmFirstChar, tm.a.tmLastChar - tm.a.tmFirstChar); + int n = tm.tmLastChar - tm.tmFirstChar; if (n <= max_font_count) { abc = new ABC[n+1]; - GetCharABCWidths(hdc, tm.w.tmFirstChar, tm.w.tmLastChar, abc); + GetCharABCWidths(hdc, tm.tmFirstChar, tm.tmLastChar, abc); } else { abc = new ABC[char_table_entries+1]; for(int i = 0; i < char_table_entries; i++) @@ -898,9 +729,6 @@ qreal QFontEngineWin::minRightBearing() const } } delete [] abc; - } else { - ml = 0; - mr = -tm.a.tmOverhang; } lbearing = ml; rbearing = mr; @@ -915,28 +743,14 @@ qreal QFontEngineWin::minRightBearing() const SelectObject(hdc, hfont); if (ttf) { ABC *abc = 0; - int n = QT_WA_INLINE(tm.w.tmLastChar - tm.w.tmFirstChar, tm.a.tmLastChar - tm.a.tmFirstChar); + int n = tm.tmLastChar - tm.tmFirstChar; if (n <= max_font_count) { abc = new ABC[n+1]; - QT_WA({ - GetCharABCWidths(hdc, tm.w.tmFirstChar, tm.w.tmLastChar, abc); - }, { - GetCharABCWidthsA(hdc,tm.a.tmFirstChar,tm.a.tmLastChar,abc); - }); + GetCharABCWidths(hdc, tm.tmFirstChar, tm.tmLastChar, abc); } else { abc = new ABC[char_table_entries+1]; - QT_WA({ - for(int i = 0; i < char_table_entries; i++) - GetCharABCWidths(hdc, char_table[i], char_table[i], abc+i); - }, { - for(int i = 0; i < char_table_entries; i++) { - QByteArray w = QString(QChar(char_table[i])).toLocal8Bit(); - if (w.length() == 1) { - uint ch8 = (uchar)w[0]; - GetCharABCWidthsA(hdc, ch8, ch8, abc+i); - } - } - }); + for(int i = 0; i < char_table_entries; i++) + GetCharABCWidths(hdc, char_table[i], char_table[i], abc + i); n = char_table_entries; } ml = abc[0].abcA; @@ -949,33 +763,28 @@ qreal QFontEngineWin::minRightBearing() const } delete [] abc; } else { - QT_WA({ - ABCFLOAT *abc = 0; - int n = tm.w.tmLastChar - tm.w.tmFirstChar+1; - if (n <= max_font_count) { - abc = new ABCFLOAT[n]; - GetCharABCWidthsFloat(hdc, tm.w.tmFirstChar, tm.w.tmLastChar, abc); - } else { - abc = new ABCFLOAT[char_table_entries]; - for(int i = 0; i < char_table_entries; i++) - GetCharABCWidthsFloat(hdc, char_table[i], char_table[i], abc+i); - n = char_table_entries; - } - float fml = abc[0].abcfA; - float fmr = abc[0].abcfC; - for (int i=1; i string->unicode() || tm.w.tmLastChar < string->unicode()) - return false; - } - }, { - while(len--) { - if (tm.a.tmFirstChar > string->unicode() || tm.a.tmLastChar < string->unicode()) - return false; - } - }); + while(len--) { + if (tm.tmFirstChar > string->unicode() || tm.tmLastChar < string->unicode()) + return false; + } } return true; } @@ -1065,11 +867,7 @@ static bool addGlyphToPath(glyph_t glyph, const QFixedPoint &position, HDC hdc, memset(&gMetric, 0, sizeof(GLYPHMETRICS)); int bufferSize = GDI_ERROR; #if !defined(Q_WS_WINCE) - QT_WA( { - bufferSize = GetGlyphOutlineW(hdc, glyph, glyphFormat, &gMetric, 0, 0, &mat); - }, { - bufferSize = GetGlyphOutlineA(hdc, glyph, glyphFormat, &gMetric, 0, 0, &mat); - }); + bufferSize = GetGlyphOutline(hdc, glyph, glyphFormat, &gMetric, 0, 0, &mat); #endif if ((DWORD)bufferSize == GDI_ERROR) { return false; @@ -1078,13 +876,7 @@ static bool addGlyphToPath(glyph_t glyph, const QFixedPoint &position, HDC hdc, void *dataBuffer = new char[bufferSize]; DWORD ret = GDI_ERROR; #if !defined(Q_WS_WINCE) - QT_WA( { - ret = GetGlyphOutlineW(hdc, glyph, glyphFormat, &gMetric, bufferSize, - dataBuffer, &mat); - }, { - ret = GetGlyphOutlineA(hdc, glyph, glyphFormat, &gMetric, bufferSize, - dataBuffer, &mat); - } ); + ret = GetGlyphOutline(hdc, glyph, glyphFormat, &gMetric, bufferSize, dataBuffer, &mat); #endif if (ret == GDI_ERROR) { delete [](char *)dataBuffer; @@ -1171,14 +963,7 @@ void QFontEngineWin::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, in // font at the correct pixel size. lf.lfHeight = -unitsPerEm; lf.lfWidth = 0; - HFONT hf; - QT_WA({ - hf = CreateFontIndirectW(&lf); - }, { - LOGFONTA lfa; - wa_copy_logfont(&lf, &lfa); - hf = CreateFontIndirectA(&lfa); - }); + HFONT hf = CreateFontIndirect(&lf); HDC hdc = shared_dc(); HGDIOBJ oldfont = SelectObject(hdc, hf); @@ -1200,7 +985,7 @@ void QFontEngineWin::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyp QPainterPath *path, QTextItem::RenderFlags flags) { #if !defined(Q_WS_WINCE) - if(tm.w.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_VECTOR)) { + if(tm.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_VECTOR)) { hasOutline = true; QFontEngine::addOutlineToPath(x, y, glyphs, path, flags); if (hasOutline) { @@ -1234,11 +1019,11 @@ int QFontEngineWin::synthesized() const uchar data[4]; GetFontData(hdc, HEAD, 44, &data, 4); USHORT macStyle = getUShort(data); - if (tm.w.tmItalic && !(macStyle & 2)) + if (tm.tmItalic && !(macStyle & 2)) synthesized_flags = SynthesizedItalic; if (fontDef.stretch != 100 && ttf) synthesized_flags |= SynthesizedStretch; - if (tm.w.tmWeight >= 500 && !(macStyle & 1)) + if (tm.tmWeight >= 500 && !(macStyle & 1)) synthesized_flags |= SynthesizedBold; //qDebug() << "font is" << _name << // "it=" << (macStyle & 2) << fontDef.style << "flags=" << synthesized_flags; @@ -1254,24 +1039,12 @@ QFixed QFontEngineWin::emSquareSize() const QFontEngine::Properties QFontEngineWin::properties() const { - LOGFONT lf = logfont; lf.lfHeight = unitsPerEm; - HFONT hf; - QT_WA({ - hf = CreateFontIndirectW(&lf); - }, { - LOGFONTA lfa; - wa_copy_logfont(&lf, &lfa); - hf = CreateFontIndirectA(&lfa); - }); + HFONT hf = CreateFontIndirect(&lf); HDC hdc = shared_dc(); HGDIOBJ oldfont = SelectObject(hdc, hf); -#if defined(Q_WS_WINCE) - OUTLINETEXTMETRICW *otm = getOutlineTextMetric(hdc); -#else - OUTLINETEXTMETRICA *otm = getOutlineTextMetric(hdc); -#endif + OUTLINETEXTMETRIC *otm = getOutlineTextMetric(hdc); Properties p; p.emSquare = unitsPerEm; p.italicAngle = otm->otmItalicAngle; @@ -1301,14 +1074,7 @@ void QFontEngineWin::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_m if(flags & SynthesizedItalic) lf.lfItalic = false; lf.lfWidth = 0; - HFONT hf; - QT_WA({ - hf = CreateFontIndirectW(&lf); - }, { - LOGFONTA lfa; - wa_copy_logfont(&lf, &lfa); - hf = CreateFontIndirectA(&lfa); - }); + HFONT hf = CreateFontIndirect(&lf); HDC hdc = shared_dc(); HGDIOBJ oldfont = SelectObject(hdc, hf); QFixedPoint p; @@ -1377,13 +1143,7 @@ QNativeImage *QFontEngineWin::drawGDIGlyph(HFONT font, glyph_t glyph, int margin memset(&mat, 0, sizeof(mat)); mat.eM11.value = mat.eM22.value = 1; - int error = 0; - QT_WA( { - error = GetGlyphOutlineW(hdc, glyph, ggo_options, &tgm, 0, 0, &mat); - }, { - error = GetGlyphOutlineA(hdc, glyph, ggo_options, &tgm, 0, 0, &mat); - } ); - + int error = GetGlyphOutline(hdc, glyph, ggo_options, &tgm, 0, 0, &mat); if (error == GDI_ERROR) { qWarning("QWinFontEngine: unable to query transformed glyph metrics..."); return 0; @@ -1430,11 +1190,11 @@ QNativeImage *QFontEngineWin::drawGDIGlyph(HFONT font, glyph_t glyph, int margin if (has_transformation) { SetGraphicsMode(hdc, GM_ADVANCED); SetWorldTransform(hdc, &xform); - ExtTextOutW(hdc, 0, 0, options, 0, (LPCWSTR) &glyph, 1, 0); + ExtTextOut(hdc, 0, 0, options, 0, (LPCWSTR) &glyph, 1, 0); } else #endif { - ExtTextOutW(hdc, -gx + margin, -gy + margin, options, 0, (LPCWSTR) &glyph, 1, 0); + ExtTextOut(hdc, -gx + margin, -gy + margin, options, 0, (LPCWSTR) &glyph, 1, 0); } SelectObject(hdc, old_font); @@ -1450,7 +1210,7 @@ QImage QFontEngineWin::alphaMapForGlyph(glyph_t glyph, const QTransform &xform) if (qt_cleartype_enabled) { LOGFONT lf = logfont; lf.lfQuality = ANTIALIASED_QUALITY; - font = CreateFontIndirectW(&lf); + font = CreateFontIndirect(&lf); } QImage::Format mask_format = QNativeImage::systemFormat(); #ifndef Q_OS_WINCE @@ -1557,17 +1317,9 @@ void QFontEngineMultiWin::loadEngine(int at) QString fam = fallbacks.at(at-1); LOGFONT lf = static_cast(engines.at(0))->logfont; - HFONT hfont; - QT_WA({ - memcpy(lf.lfFaceName, fam.utf16(), sizeof(TCHAR)*qMin(fam.length()+1,32)); // 32 = Windows hard-coded - hfont = CreateFontIndirectW(&lf); - } , { - // LOGFONTA and LOGFONTW are binary compatible - QByteArray lname = fam.toLocal8Bit(); - memcpy(lf.lfFaceName,lname.data(), - qMin(lname.length()+1,32)); // 32 = Windows hard-coded - hfont = CreateFontIndirectA((LOGFONTA*)&lf); - }); + memcpy(lf.lfFaceName, fam.utf16(), sizeof(wchar_t) * qMin(fam.length() + 1, 32)); // 32 = Windows hard-coded + HFONT hfont = CreateFontIndirect(&lf); + bool stockFont = false; if (hfont == 0) { hfont = (HFONT)GetStockObject(ANSI_VAR_FONT); diff --git a/src/gui/text/qfontengine_win_p.h b/src/gui/text/qfontengine_win_p.h index a8da78a..b86bd00 100644 --- a/src/gui/text/qfontengine_win_p.h +++ b/src/gui/text/qfontengine_win_p.h @@ -80,7 +80,7 @@ public: virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs, QPainterPath *path, QTextItem::RenderFlags flags); - HGDIOBJ selectDesignFont(QFixed *) const; + HGDIOBJ selectDesignFont() const; virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs); virtual glyph_metrics_t boundingBox(glyph_t g) { return boundingBox(g, QTransform()); } @@ -109,18 +109,14 @@ public: int getGlyphIndexes(const QChar *ch, int numChars, QGlyphLayout *glyphs, bool mirrored) const; void getCMap(); - QString _name; - HFONT hfont; + QString _name; + HFONT hfont; LOGFONT logfont; - uint stockFont : 1; - uint useTextOutA : 1; - uint ttf : 1; + uint stockFont : 1; + uint ttf : 1; uint hasOutline : 1; - union { - TEXTMETRICW w; - TEXTMETRICA a; - } tm; - int lw; + TEXTMETRIC tm; + int lw; const unsigned char *cmap; QByteArray cmapTable; mutable qreal lbearing; diff --git a/src/gui/util/qdesktopservices_win.cpp b/src/gui/util/qdesktopservices_win.cpp index 2cc478d..e872617 100644 --- a/src/gui/util/qdesktopservices_win.cpp +++ b/src/gui/util/qdesktopservices_win.cpp @@ -62,33 +62,23 @@ QT_BEGIN_NAMESPACE -//#undef UNICODE - static bool openDocument(const QUrl &file) { if (!file.isValid()) return false; - quintptr returnValue; - QT_WA({ - returnValue = (quintptr)ShellExecute(0, 0, (TCHAR *)file.toString().utf16(), 0, 0, SW_SHOWNORMAL); - } , { - returnValue = (quintptr)ShellExecuteA(0, 0, file.toString().toLocal8Bit().constData(), 0, 0, SW_SHOWNORMAL); - }); + quintptr returnValue = (quintptr)ShellExecute(0, 0, (wchar_t*)file.toString().utf16(), 0, 0, SW_SHOWNORMAL); return (returnValue > 32); //ShellExecute returns a value greater than 32 if successful } static QString expandEnvStrings(const QString &command) { - #if defined(Q_OS_WINCE) return command; #else - QByteArray path = command.toLocal8Bit(); - char commandValue[2 * MAX_PATH] = {0}; - DWORD returnValue = ExpandEnvironmentStringsA(path.data(), commandValue, MAX_PATH); - if (returnValue) - return QString::fromLocal8Bit(commandValue); + wchar_t buffer[MAX_PATH]; + if (ExpandEnvironmentStrings((wchar_t*)command.utf16(), buffer, MAX_PATH)) + return QString::fromWCharArray(buffer); else return command; #endif @@ -129,8 +119,9 @@ static bool launchWebBrowser(const QUrl &url) command = QString::fromRawData((QChar*)keyValue, bufferSize); RegCloseKey(handle); - if(returnValue) + if (returnValue) return false; + command = expandEnvStrings(command); command = command.trimmed(); //Make sure the path for the process is in quotes @@ -152,7 +143,7 @@ static bool launchWebBrowser(const QUrl &url) ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); - returnValue = CreateProcess(NULL, (TCHAR*)command.utf16(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); + returnValue = CreateProcess(NULL, (wchar_t*)command.utf16(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); if (!returnValue) return false; @@ -168,9 +159,8 @@ static bool launchWebBrowser(const QUrl &url) if (url.scheme().isEmpty()) return openDocument(url); - quintptr returnValue; - returnValue = (quintptr)ShellExecute(0, 0, (TCHAR *) QString::fromUtf8(url.toEncoded().constData()).utf16(), - 0, 0, SW_SHOWNORMAL); + quintptr returnValue = (quintptr)ShellExecute(0, 0, (wchar_t *)QString::fromUtf8(url.toEncoded().constData()).utf16(), + 0, 0, SW_SHOWNORMAL); return (returnValue > 32); } diff --git a/src/gui/util/qsystemtrayicon_win.cpp b/src/gui/util/qsystemtrayicon_win.cpp index d2ce1be..c1b7e7f 100644 --- a/src/gui/util/qsystemtrayicon_win.cpp +++ b/src/gui/util/qsystemtrayicon_win.cpp @@ -41,8 +41,7 @@ #include "qsystemtrayicon_p.h" #ifndef QT_NO_SYSTEMTRAYICON -//#define _WIN32_IE 0x0500 -#define _WIN32_IE 0x0600 //required for NOTIFYICONDATAW_V2_SIZE +#define _WIN32_IE 0x0600 //required for NOTIFYICONDATA_V2_SIZE //missing defines for MINGW : #ifndef NIN_BALLOONTIMEOUT @@ -77,25 +76,14 @@ static const UINT q_uNOTIFYICONID = 0; static uint MYWM_TASKBARCREATED = 0; #define MYWM_NOTIFYICON (WM_APP+101) -typedef BOOL (WINAPI *PtrShell_NotifyIcon)(DWORD,PNOTIFYICONDATA); -static PtrShell_NotifyIcon ptrShell_NotifyIcon = 0; +struct Q_NOTIFYICONIDENTIFIER { + DWORD cbSize; + HWND hWnd; + UINT uID; + GUID guidItem; +}; -static void resolveLibs() -{ - static bool triedResolve = false; -#if defined Q_OS_WINCE - QString libName(QLatin1String("coredll")); - const char* funcName = "Shell_NotifyIcon"; -#else - QString libName(QLatin1String("shell32")); - const char* funcName = "Shell_NotifyIconW"; -#endif - if (!triedResolve) { - QLibrary lib(libName); - triedResolve = true; - ptrShell_NotifyIcon = (PtrShell_NotifyIcon) lib.resolve(funcName); - } -} +typedef HRESULT (WINAPI *PtrShell_NotifyIconGetRect)(const Q_NOTIFYICONIDENTIFIER* identifier, RECT* iconLocation); class QSystemTrayIconSys : QWidget { @@ -103,37 +91,26 @@ public: QSystemTrayIconSys(QSystemTrayIcon *object); ~QSystemTrayIconSys(); bool winEvent( MSG *m, long *result ); - bool trayMessageA(DWORD msg); - bool trayMessageW(DWORD msg); bool trayMessage(DWORD msg); bool iconDrawItem(LPDRAWITEMSTRUCT lpdi); - void setIconContentsW(NOTIFYICONDATAW &data); - void setIconContentsA(NOTIFYICONDATAA &data); - bool showMessageW(const QString &title, const QString &message, QSystemTrayIcon::MessageIcon type, uint uSecs); - bool showMessageA(const QString &title, const QString &message, QSystemTrayIcon::MessageIcon type, uint uSecs); + void setIconContents(NOTIFYICONDATA &data); + bool showMessage(const QString &title, const QString &message, QSystemTrayIcon::MessageIcon type, uint uSecs); bool allowsMessages(); bool supportsMessages(); QRect findIconGeometry(const int a_iButtonID); - QRect findTrayGeometry(); HBITMAP createIconMask(const QBitmap &bitmap); void createIcon(); - int detectShellVersion() const; HICON hIcon; QPoint globalPos; QSystemTrayIcon *q; private: - uint notifyIconSizeW; - uint notifyIconSizeA; - int currentShellVersion; + uint notifyIconSize; int maxTipLength; }; -// Checks for the shell32 dll version number, since only version -// 5 or later of supports ballon messages bool QSystemTrayIconSys::allowsMessages() { #ifndef QT_NO_SETTINGS - QSettings settings(QLatin1String("HKEY_CURRENT_USER\\Software\\Microsoft" "\\Windows\\CurrentVersion\\Explorer\\Advanced"), QSettings::NativeFormat); return settings.value(QLatin1String("EnableBalloonTips"), true).toBool(); @@ -142,63 +119,28 @@ bool QSystemTrayIconSys::allowsMessages() #endif } -// Checks for the shell32 dll version number, since only version -// 5 or later of supports ballon messages bool QSystemTrayIconSys::supportsMessages() { -#if NOTIFYICON_VERSION >= 3 - if (currentShellVersion >= 5) - return allowsMessages(); - else -#endif - return false; -} - -//Returns the runtime major version of the shell32 dll -int QSystemTrayIconSys::detectShellVersion() const -{ #ifndef Q_OS_WINCE - int shellVersion = 4; //NT 4.0 and W95 - DLLGETVERSIONPROC pDllGetVersion = (DLLGETVERSIONPROC)QLibrary::resolve( - QLatin1String("shell32"), "DllGetVersion"); - if (pDllGetVersion) - { - DLLVERSIONINFO dvi; - HRESULT hr; - ZeroMemory(&dvi, sizeof(dvi)); - dvi.cbSize = sizeof(dvi); - hr = (*pDllGetVersion)(&dvi); - if (SUCCEEDED(hr)) { - if (dvi.dwMajorVersion >= 5) - { - shellVersion = dvi.dwMajorVersion; - } - } - } - return shellVersion; + return allowsMessages(); #endif - return 4; //No ballonMessages and MaxTipLength = 64 for WindowsCE + return false; } QSystemTrayIconSys::QSystemTrayIconSys(QSystemTrayIcon *object) : hIcon(0), q(object) { - currentShellVersion = detectShellVersion(); - notifyIconSizeA = FIELD_OFFSET(NOTIFYICONDATAA, szTip[64]); // NOTIFYICONDATAA_V1_SIZE - notifyIconSizeW = FIELD_OFFSET(NOTIFYICONDATAW, szTip[64]); // NOTIFYICONDATAW_V1_SIZE; +#ifndef Q_OS_WINCE + notifyIconSize = FIELD_OFFSET(NOTIFYICONDATA, guidItem); // NOTIFYICONDATAW_V2_SIZE; + maxTipLength = 128; +#else + notifyIconSize = FIELD_OFFSET(NOTIFYICONDATA, szTip[64]); // NOTIFYICONDATAW_V1_SIZE; maxTipLength = 64; - -#if NOTIFYICON_VERSION >= 3 - if (currentShellVersion >=5) { - notifyIconSizeA = FIELD_OFFSET(NOTIFYICONDATAA, guidItem); // NOTIFYICONDATAA_V2_SIZE - notifyIconSizeW = FIELD_OFFSET(NOTIFYICONDATAW, guidItem); // NOTIFYICONDATAW_V2_SIZE; - maxTipLength = 128; - } #endif // For restoring the tray icon after explorer crashes if (!MYWM_TASKBARCREATED) { - MYWM_TASKBARCREATED = QT_WA_INLINE(RegisterWindowMessageW(L"TaskbarCreated"),RegisterWindowMessageA("TaskbarCreated")); + MYWM_TASKBARCREATED = RegisterWindowMessage(L"TaskbarCreated"); } } @@ -208,118 +150,60 @@ QSystemTrayIconSys::~QSystemTrayIconSys() DestroyIcon(hIcon); } -void QSystemTrayIconSys::setIconContentsW(NOTIFYICONDATAW &tnd) +void QSystemTrayIconSys::setIconContents(NOTIFYICONDATA &tnd) { - tnd.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP; + tnd.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP; tnd.uCallbackMessage = MYWM_NOTIFYICON; tnd.hIcon = hIcon; QString tip = q->toolTip(); if (!tip.isNull()) { - // Tip is limited to maxTipLength - NULL; lstrcpyn appends a NULL terminator. tip = tip.left(maxTipLength - 1) + QChar(); -#if defined(Q_OS_WINCE) - wcsncpy(tnd.szTip, reinterpret_cast (tip.utf16()), qMin(tip.length()+1, maxTipLength)); -#else - lstrcpynW(tnd.szTip, (TCHAR*)tip.utf16(), qMin(tip.length()+1, maxTipLength)); -#endif - } -} - -void QSystemTrayIconSys::setIconContentsA(NOTIFYICONDATAA &tnd) -{ - tnd.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP; - tnd.uCallbackMessage = MYWM_NOTIFYICON; - tnd.hIcon = hIcon; - QString tip = q->toolTip(); - - if (!tip.isNull()) { - // Tip is limited to maxTipLength - NULL; lstrcpyn appends a NULL terminator. - tip = tip.left(maxTipLength - 1) + QChar(); -#if defined(Q_OS_WINCE) - strncpy(tnd.szTip, tip.toLocal8Bit().constData(), qMin(tip.length()+1, maxTipLength)); -#else - lstrcpynA(tnd.szTip, tip.toLocal8Bit().constData(), qMin(tip.length()+1, maxTipLength)); -#endif + memcpy(tnd.szTip, tip.utf16(), qMin(tip.length() + 1, maxTipLength) * sizeof(wchar_t)); } } int iconFlag( QSystemTrayIcon::MessageIcon icon ) { - int flag = 0; #if NOTIFYICON_VERSION >= 3 switch (icon) { - case QSystemTrayIcon::NoIcon: - break; - case QSystemTrayIcon::Critical: - flag = NIIF_ERROR; - break; - case QSystemTrayIcon::Warning: - flag = NIIF_WARNING; - break; case QSystemTrayIcon::Information: - default : // fall through - flag = NIIF_INFO; + return NIIF_INFO; + case QSystemTrayIcon::Warning: + return NIIF_WARNING; + case QSystemTrayIcon::Critical: + return NIIF_ERROR; + case QSystemTrayIcon::NoIcon: + return NIIF_NONE; + default: + Q_ASSERT("Invalid QSystemTrayIcon::MessageIcon value", false); + return NIIF_NONE; } #else Q_UNUSED(icon); + return 0; #endif - return flag; } -bool QSystemTrayIconSys::showMessageW(const QString &title, const QString &message, QSystemTrayIcon::MessageIcon type, uint uSecs) +bool QSystemTrayIconSys::showMessage(const QString &title, const QString &message, QSystemTrayIcon::MessageIcon type, uint uSecs) { -#if NOTIFYICON_VERSION>=3 +#if NOTIFYICON_VERSION >= 3 NOTIFYICONDATA tnd; - memset(&tnd, 0, notifyIconSizeW); + memset(&tnd, 0, notifyIconSize); Q_ASSERT(testAttribute(Qt::WA_WState_Created)); - setIconContentsW(tnd); -#if defined(Q_OS_WINCE) - wcsncpy(tnd.szInfo, message.utf16(), qMin(message.length() + 1, 256)); - wcsncpy(tnd.szInfoTitle, title.utf16(), qMin(title.length()+1, 64)); -#else - lstrcpynW(tnd.szInfo, (TCHAR*)message.utf16(), qMin(message.length() + 1, 256)); - lstrcpynW(tnd.szInfoTitle, (TCHAR*)title.utf16(), qMin(title.length() + 1, 64)); -#endif - tnd.uID = q_uNOTIFYICONID; - tnd.dwInfoFlags = iconFlag(type); - tnd.cbSize = notifyIconSizeW; - tnd.hWnd = winId(); - tnd.uTimeout = uSecs; - tnd.uFlags = NIF_INFO; - return ptrShell_NotifyIcon(NIM_MODIFY, &tnd); -#else - Q_UNUSED(title); - Q_UNUSED(message); - Q_UNUSED(type); - Q_UNUSED(uSecs); - return false; -#endif -} - -bool QSystemTrayIconSys::showMessageA(const QString &title, const QString &message, QSystemTrayIcon::MessageIcon type, uint uSecs) -{ -#if NOTIFYICON_VERSION>=3 - NOTIFYICONDATAA tnd; - memset(&tnd, 0, notifyIconSizeA); - Q_ASSERT(testAttribute(Qt::WA_WState_Created)); + setIconContents(tnd); + memcpy(tnd.szInfo, message.utf16(), qMin(message.length() + 1, 256) * sizeof(wchar_t)); + memcpy(tnd.szInfoTitle, title.utf16(), qMin(title.length() + 1, 64) * sizeof(wchar_t)); - setIconContentsA(tnd); -#if defined(Q_OS_WINCE) - strncpy(tnd.szInfo, message.toLocal8Bit().constData(), qMin(message.length() + 1, 256)); - strncpy(tnd.szInfoTitle, title.toLocal8Bit().constData(), qMin(title.length()+1, 64)); -#else - lstrcpynA(tnd.szInfo, message.toLocal8Bit().constData(), qMin(message.length() + 1, 256)); - lstrcpynA(tnd.szInfoTitle, title.toLocal8Bit().constData(), qMin(title.length() + 1, 64)); -#endif tnd.uID = q_uNOTIFYICONID; tnd.dwInfoFlags = iconFlag(type); - tnd.cbSize = notifyIconSizeA; + tnd.cbSize = notifyIconSize; tnd.hWnd = winId(); tnd.uTimeout = uSecs; tnd.uFlags = NIF_INFO; - return Shell_NotifyIconA(NIM_MODIFY, &tnd); + + return Shell_NotifyIcon(NIM_MODIFY, &tnd); #else Q_UNUSED(title); Q_UNUSED(message); @@ -329,53 +213,21 @@ bool QSystemTrayIconSys::showMessageA(const QString &title, const QString &messa #endif } -bool QSystemTrayIconSys::trayMessageA(DWORD msg) +bool QSystemTrayIconSys::trayMessage(DWORD msg) { -#if !defined(Q_WS_WINCE) - NOTIFYICONDATAA tnd; - memset(&tnd, 0, notifyIconSizeA); + NOTIFYICONDATA tnd; + memset(&tnd, 0, notifyIconSize); tnd.uID = q_uNOTIFYICONID; - tnd.cbSize = notifyIconSizeA; + tnd.cbSize = notifyIconSize; tnd.hWnd = winId(); - Q_ASSERT(testAttribute(Qt::WA_WState_Created)); - if (msg != NIM_DELETE) { - setIconContentsA(tnd); - } - return Shell_NotifyIconA(msg, &tnd); -#else - Q_UNUSED(msg); - return false; -#endif -} - -bool QSystemTrayIconSys::trayMessageW(DWORD msg) -{ - NOTIFYICONDATAW tnd; - memset(&tnd, 0, notifyIconSizeW); - tnd.uID = q_uNOTIFYICONID; - tnd.cbSize = notifyIconSizeW; - tnd.hWnd = winId(); Q_ASSERT(testAttribute(Qt::WA_WState_Created)); if (msg != NIM_DELETE) { - setIconContentsW(tnd); + setIconContents(tnd); } - return ptrShell_NotifyIcon(msg, &tnd); -} -bool QSystemTrayIconSys::trayMessage(DWORD msg) -{ - resolveLibs(); - if (!(ptrShell_NotifyIcon)) - return false; - - QT_WA({ - return trayMessageW(msg); - }, - { - return trayMessageA(msg); - }); + return Shell_NotifyIcon(msg, &tnd); } bool QSystemTrayIconSys::iconDrawItem(LPDRAWITEMSTRUCT lpdi) @@ -514,33 +366,6 @@ void QSystemTrayIconPrivate::install_sys() } } -//fallback on win 95/98 -QRect QSystemTrayIconSys::findTrayGeometry() -{ - //Use lower right corner as fallback - QPoint brCorner = QApplication::desktop()->screenGeometry().bottomRight(); - QRect ret(brCorner.x() - 10, brCorner.y() - 10, 10, 10); -#if defined(Q_OS_WINCE) - HWND trayHandle = FindWindowW(L"Shell_TrayWnd", NULL); -#else - HWND trayHandle = FindWindowA("Shell_TrayWnd", NULL); -#endif - if (trayHandle) { -#if defined(Q_OS_WINCE) - trayHandle = FindWindowW(L"TrayNotifyWnd", NULL); -#else - trayHandle = FindWindowExA(trayHandle, NULL, "TrayNotifyWnd", NULL); -#endif - if (trayHandle) { - RECT r; - if (GetWindowRect(trayHandle, &r)) { - ret = QRect(r.left, r.top, r.right- r.left, r.bottom - r.top); - } - } - } - return ret; -} - /* * This function tries to determine the icon geometry from the tray * @@ -548,26 +373,39 @@ QRect QSystemTrayIconSys::findTrayGeometry() */ QRect QSystemTrayIconSys::findIconGeometry(const int iconId) { + static PtrShell_NotifyIconGetRect Shell_NotifyIconGetRect = + (PtrShell_NotifyIconGetRect)QLibrary::resolve(QLatin1String("shell32"), "Shell_NotifyIconGetRect"); + + if (Shell_NotifyIconGetRect) { + Q_NOTIFYICONIDENTIFIER nid; + memset(&nid, 0, sizeof(nid)); + nid.cbSize = sizeof(nid); + nid.hWnd = winId(); + nid.uID = iconId; + + RECT rect; + HRESULT hr = Shell_NotifyIconGetRect(&nid, &rect); + if (SUCCEEDED(hr)) { + return QRect(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top); + } + } + QRect ret; TBBUTTON buttonData; DWORD processID = 0; -#if defined(Q_OS_WINCE) - HWND trayHandle = FindWindowW(L"Shell_TrayWnd", NULL); -#else - HWND trayHandle = FindWindowA("Shell_TrayWnd", NULL); -#endif + HWND trayHandle = FindWindow(L"Shell_TrayWnd", NULL); //find the toolbar used in the notification area if (trayHandle) { #if defined(Q_OS_WINCE) - trayHandle = FindWindowW(L"TrayNotifyWnd", NULL); + trayHandle = FindWindow(L"TrayNotifyWnd", NULL); #else - trayHandle = FindWindowExA(trayHandle, NULL, "TrayNotifyWnd", NULL); + trayHandle = FindWindowEx(trayHandle, NULL, L"TrayNotifyWnd", NULL); #endif if (trayHandle) { #if defined(Q_OS_WINCE) - HWND hwnd = FindWindowW(L"SysPager", NULL); + HWND hwnd = FindWindow(L"SysPager", NULL); #else HWND hwnd = FindWindowEx(trayHandle, NULL, L"SysPager", NULL); #endif @@ -612,10 +450,10 @@ QRect QSystemTrayIconSys::findIconGeometry(const int iconId) DWORD appData[2] = { 0, 0 }; SendMessage(trayHandle, TB_GETBUTTON, toolbarButton , (LPARAM)data); - if(!ReadProcessMemory(trayProcess, data, &buttonData, sizeof(TBBUTTON), &numBytes)) + if (!ReadProcessMemory(trayProcess, data, &buttonData, sizeof(TBBUTTON), &numBytes)) continue; - if(!ReadProcessMemory(trayProcess, (LPVOID) buttonData.dwData, appData, sizeof(appData), &numBytes)) + if (!ReadProcessMemory(trayProcess, (LPVOID) buttonData.dwData, appData, sizeof(appData), &numBytes)) continue; int currentIconId = appData[1]; @@ -646,7 +484,6 @@ QRect QSystemTrayIconSys::findIconGeometry(const int iconId) return ret; } - void QSystemTrayIconPrivate::showMessage_sys(const QString &title, const QString &message, QSystemTrayIcon::MessageIcon type, int timeOut) { if (!sys || !sys->allowsMessages()) @@ -657,8 +494,6 @@ void QSystemTrayIconPrivate::showMessage_sys(const QString &title, const QString uSecs = 10000; //10 sec default else uSecs = (int)timeOut; - resolveLibs(); - //message is limited to 255 chars + NULL QString messageString; if (message.isEmpty() && !title.isEmpty()) @@ -670,20 +505,12 @@ void QSystemTrayIconPrivate::showMessage_sys(const QString &title, const QString QString titleString = title.left(63) + QChar(); if (sys->supportsMessages()) { - QT_WA({ - sys->showMessageW(titleString, messageString, type, (unsigned int)uSecs); - }, { - sys->showMessageA(titleString, messageString, type, (unsigned int)uSecs); - }); + sys->showMessage(titleString, messageString, type, (unsigned int)uSecs); } else { - //use fallbacks - QRect iconPos = sys->findIconGeometry(0); + //use fallback + QRect iconPos = sys->findIconGeometry(q_uNOTIFYICONID); if (iconPos.isValid()) { QBalloonTip::showBalloon(type, title, message, sys->q, iconPos.center(), uSecs, true); - } else { - QRect trayRect = sys->findTrayGeometry(); - QBalloonTip::showBalloon(type, title, message, sys->q, QPoint(trayRect.left(), - trayRect.center().y()), uSecs, false); } } } @@ -692,7 +519,7 @@ QRect QSystemTrayIconPrivate::geometry_sys() const { if (!sys) return QRect(); - return sys->findIconGeometry(0); + return sys->findIconGeometry(q_uNOTIFYICONID); } void QSystemTrayIconPrivate::remove_sys() diff --git a/src/gui/widgets/qeffects.cpp b/src/gui/widgets/qeffects.cpp index 065a2e0..d6d0a16 100644 --- a/src/gui/widgets/qeffects.cpp +++ b/src/gui/widgets/qeffects.cpp @@ -126,10 +126,9 @@ QAlphaWidget::QAlphaWidget(QWidget* w, Qt::WindowFlags f) QAlphaWidget::~QAlphaWidget() { -#ifdef Q_WS_WIN +#if defined(Q_WS_WIN) && !defined(Q_WS_WINCE) // Restore user-defined opacity value - if (widget && QSysInfo::WindowsVersion >= QSysInfo::WV_2000 && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based) - widget->setWindowOpacity(windowOpacity); + widget->setWindowOpacity(windowOpacity); #endif } @@ -160,43 +159,40 @@ void QAlphaWidget::run(int time) checkTime.start(); showWidget = true; -#if defined(Q_OS_WIN) - if (QSysInfo::WindowsVersion >= QSysInfo::WV_2000 && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based) { - qApp->installEventFilter(this); - widget->setWindowOpacity(0.0); - widget->show(); +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) + qApp->installEventFilter(this); + widget->setWindowOpacity(0.0); + widget->show(); + connect(&anim, SIGNAL(timeout()), this, SLOT(render())); + anim.start(1); +#else + //This is roughly equivalent to calling setVisible(true) without actually showing the widget + widget->setAttribute(Qt::WA_WState_ExplicitShowHide, true); + widget->setAttribute(Qt::WA_WState_Hidden, false); + + qApp->installEventFilter(this); + + move(widget->geometry().x(),widget->geometry().y()); + resize(widget->size().width(), widget->size().height()); + + frontImage = QPixmap::grabWidget(widget).toImage(); + backImage = QPixmap::grabWindow(QApplication::desktop()->winId(), + widget->geometry().x(), widget->geometry().y(), + widget->geometry().width(), widget->geometry().height()).toImage(); + + if (!backImage.isNull() && checkTime.elapsed() < duration / 2) { + mixedImage = backImage.copy(); + pm = QPixmap::fromImage(mixedImage); + show(); + setEnabled(false); + connect(&anim, SIGNAL(timeout()), this, SLOT(render())); anim.start(1); - } else -#endif - { - //This is roughly equivalent to calling setVisible(true) without actually showing the widget - widget->setAttribute(Qt::WA_WState_ExplicitShowHide, true); - widget->setAttribute(Qt::WA_WState_Hidden, false); - - qApp->installEventFilter(this); - - move(widget->geometry().x(),widget->geometry().y()); - resize(widget->size().width(), widget->size().height()); - - frontImage = QPixmap::grabWidget(widget).toImage(); - backImage = QPixmap::grabWindow(QApplication::desktop()->winId(), - widget->geometry().x(), widget->geometry().y(), - widget->geometry().width(), widget->geometry().height()).toImage(); - - if (!backImage.isNull() && checkTime.elapsed() < duration / 2) { - mixedImage = backImage.copy(); - pm = QPixmap::fromImage(mixedImage); - show(); - setEnabled(false); - - connect(&anim, SIGNAL(timeout()), this, SLOT(render())); - anim.start(1); - } else { - duration = 0; - render(); - } + } else { + duration = 0; + render(); } +#endif } /* @@ -270,19 +266,17 @@ void QAlphaWidget::render() else alpha = 1; -#if defined(Q_OS_WIN) - if (QSysInfo::WindowsVersion >= QSysInfo::WV_2000 && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based) { - if (alpha >= windowOpacity || !showWidget) { - anim.stop(); - qApp->removeEventFilter(this); - widget->setWindowOpacity(windowOpacity); - q_blend = 0; - deleteLater(); - } else { - widget->setWindowOpacity(alpha); - } - } else -#endif +#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) + if (alpha >= windowOpacity || !showWidget) { + anim.stop(); + qApp->removeEventFilter(this); + widget->setWindowOpacity(windowOpacity); + q_blend = 0; + deleteLater(); + } else { + widget->setWindowOpacity(alpha); + } +#else if (alpha >= 1 || !showWidget) { anim.stop(); qApp->removeEventFilter(this); @@ -292,7 +286,7 @@ void QAlphaWidget::render() #ifdef Q_WS_WIN setEnabled(true); setFocus(); -#endif +#endif // Q_WS_WIN widget->hide(); } else { //Since we are faking the visibility of the widget @@ -309,6 +303,7 @@ void QAlphaWidget::render() pm = QPixmap::fromImage(mixedImage); repaint(); } +#endif // defined(Q_OS_WIN) && !defined(Q_OS_WINCE) } /* diff --git a/src/gui/widgets/qframe.cpp b/src/gui/widgets/qframe.cpp index b9e769d..a87ec85 100644 --- a/src/gui/widgets/qframe.cpp +++ b/src/gui/widgets/qframe.cpp @@ -135,7 +135,7 @@ inline void QFramePrivate::init() \value VLine QFrame draws a vertical line that frames nothing (useful as separator) \value WinPanel draws a rectangular panel that can be raised or - sunken like those in Windows 95. Specifying this shape sets + sunken like those in Windows 2000. Specifying this shape sets the line width to 2 pixels. WinPanel is provided for compatibility. For GUI style independence we recommend using StyledPanel instead. diff --git a/src/gui/widgets/qmdisubwindow.cpp b/src/gui/widgets/qmdisubwindow.cpp index 25bc724..24dea37 100644 --- a/src/gui/widgets/qmdisubwindow.cpp +++ b/src/gui/widgets/qmdisubwindow.cpp @@ -1946,26 +1946,21 @@ QPalette QMdiSubWindowPrivate::desktopPalette() const colorref2qrgb(GetSysColor(COLOR_CAPTIONTEXT))); newPalette.setColor(QPalette::Inactive, QPalette::HighlightedText, colorref2qrgb(GetSysColor(COLOR_INACTIVECAPTIONTEXT))); - if (QSysInfo::WindowsVersion != QSysInfo::WV_95 - && QSysInfo::WindowsVersion != QSysInfo::WV_NT) { - colorsInitialized = true; - BOOL hasGradient; - QT_WA({ - SystemParametersInfo(SPI_GETGRADIENTCAPTIONS, 0, &hasGradient, 0); - } , { - SystemParametersInfoA(SPI_GETGRADIENTCAPTIONS, 0, &hasGradient, 0); - }); - if (hasGradient) { - newPalette.setColor(QPalette::Active, QPalette::Base, - colorref2qrgb(GetSysColor(COLOR_GRADIENTACTIVECAPTION))); - newPalette.setColor(QPalette::Inactive, QPalette::Base, - colorref2qrgb(GetSysColor(COLOR_GRADIENTINACTIVECAPTION))); - } else { - newPalette.setColor(QPalette::Active, QPalette::Base, - newPalette.color(QPalette::Active, QPalette::Highlight)); - newPalette.setColor(QPalette::Inactive, QPalette::Base, - newPalette.color(QPalette::Inactive, QPalette::Highlight)); - } + + colorsInitialized = true; + BOOL hasGradient = false; + SystemParametersInfo(SPI_GETGRADIENTCAPTIONS, 0, &hasGradient, 0); + + if (hasGradient) { + newPalette.setColor(QPalette::Active, QPalette::Base, + colorref2qrgb(GetSysColor(COLOR_GRADIENTACTIVECAPTION))); + newPalette.setColor(QPalette::Inactive, QPalette::Base, + colorref2qrgb(GetSysColor(COLOR_GRADIENTINACTIVECAPTION))); + } else { + newPalette.setColor(QPalette::Active, QPalette::Base, + newPalette.color(QPalette::Active, QPalette::Highlight)); + newPalette.setColor(QPalette::Inactive, QPalette::Base, + newPalette.color(QPalette::Inactive, QPalette::Highlight)); } } #endif // Q_WS_WIN diff --git a/src/gui/widgets/qsizegrip.cpp b/src/gui/widgets/qsizegrip.cpp index d263b9c..c6aae68 100644 --- a/src/gui/widgets/qsizegrip.cpp +++ b/src/gui/widgets/qsizegrip.cpp @@ -335,8 +335,7 @@ void QSizeGrip::mousePressEvent(QMouseEvent * e) orientation = d->atLeft() ? SZ_SIZETOPLEFT : SZ_SIZETOPRIGHT; ReleaseCapture(); - QT_WA_INLINE(PostMessageW(tlw->winId(), WM_SYSCOMMAND, orientation, 0), - PostMessageA(tlw->winId(), WM_SYSCOMMAND, orientation, 0)); + PostMessage(tlw->winId(), WM_SYSCOMMAND, orientation, 0); return; } #endif // Q_WS_WIN diff --git a/src/gui/widgets/qworkspace.cpp b/src/gui/widgets/qworkspace.cpp index 58ef1e3..2833c08 100644 --- a/src/gui/widgets/qworkspace.cpp +++ b/src/gui/widgets/qworkspace.cpp @@ -397,21 +397,17 @@ void QWorkspaceTitleBarPrivate::readColors() pal.setColor(QPalette::Inactive, QPalette::Highlight, colorref2qrgb(GetSysColor(COLOR_INACTIVECAPTION))); pal.setColor(QPalette::Active, QPalette::HighlightedText, colorref2qrgb(GetSysColor(COLOR_CAPTIONTEXT))); pal.setColor(QPalette::Inactive, QPalette::HighlightedText, colorref2qrgb(GetSysColor(COLOR_INACTIVECAPTIONTEXT))); - if (QSysInfo::WindowsVersion != QSysInfo::WV_95 && QSysInfo::WindowsVersion != QSysInfo::WV_NT) { - colorsInitialized = true; - BOOL gradient; - QT_WA({ - SystemParametersInfo(SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0); - } , { - SystemParametersInfoA(SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0); - }); - if (gradient) { - pal.setColor(QPalette::Active, QPalette::Base, colorref2qrgb(GetSysColor(COLOR_GRADIENTACTIVECAPTION))); - pal.setColor(QPalette::Inactive, QPalette::Base, colorref2qrgb(GetSysColor(COLOR_GRADIENTINACTIVECAPTION))); - } else { - pal.setColor(QPalette::Active, QPalette::Base, pal.color(QPalette::Active, QPalette::Highlight)); - pal.setColor(QPalette::Inactive, QPalette::Base, pal.color(QPalette::Inactive, QPalette::Highlight)); - } + + colorsInitialized = true; + BOOL gradient = false; + SystemParametersInfo(SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0); + + if (gradient) { + pal.setColor(QPalette::Active, QPalette::Base, colorref2qrgb(GetSysColor(COLOR_GRADIENTACTIVECAPTION))); + pal.setColor(QPalette::Inactive, QPalette::Base, colorref2qrgb(GetSysColor(COLOR_GRADIENTINACTIVECAPTION))); + } else { + pal.setColor(QPalette::Active, QPalette::Base, pal.color(QPalette::Active, QPalette::Highlight)); + pal.setColor(QPalette::Inactive, QPalette::Base, pal.color(QPalette::Inactive, QPalette::Highlight)); } } #endif // Q_WS_WIN -- cgit v0.12 From 48406f5ae81fdcb3ba2a01471678d10213a2caa9 Mon Sep 17 00:00:00 2001 From: miniak Date: Wed, 1 Jul 2009 11:49:58 +0200 Subject: src/network: Remove QT_WA and non-Unicode code paths, dropping Win9x and NT support Merge-request: 604 Reviewed-by: Marius Storm-Olsen --- src/network/kernel/qnetworkinterface_win.cpp | 15 +++---- src/network/kernel/qnetworkproxy_win.cpp | 15 +------ src/network/socket/qlocalserver.cpp | 2 - src/network/socket/qlocalserver_win.cpp | 19 ++------- src/network/socket/qlocalsocket.cpp | 2 - src/network/socket/qlocalsocket_win.cpp | 36 +++++----------- src/network/socket/qnativesocketengine_win.cpp | 58 +++++++++++--------------- 7 files changed, 43 insertions(+), 104 deletions(-) diff --git a/src/network/kernel/qnetworkinterface_win.cpp b/src/network/kernel/qnetworkinterface_win.cpp index 0165385..87902c3 100644 --- a/src/network/kernel/qnetworkinterface_win.cpp +++ b/src/network/kernel/qnetworkinterface_win.cpp @@ -66,19 +66,14 @@ static void resolveLibs() if (!done) { done = true; - HINSTANCE iphlpapiHnd; - QT_WA({ - iphlpapiHnd = LoadLibraryW(L"iphlpapi"); - }, { - iphlpapiHnd = LoadLibraryA("iphlpapi"); - }); + HINSTANCE iphlpapiHnd = LoadLibrary(L"iphlpapi"); if (iphlpapiHnd == NULL) - return; // failed to load, probably Windows 95 + return; #if defined(Q_OS_WINCE) - ptrGetAdaptersInfo = (PtrGetAdaptersInfo)GetProcAddressW(iphlpapiHnd, L"GetAdaptersInfo"); - ptrGetAdaptersAddresses = (PtrGetAdaptersAddresses)GetProcAddressW(iphlpapiHnd, L"GetAdaptersAddresses"); - ptrGetNetworkParams = (PtrGetNetworkParams)GetProcAddressW(iphlpapiHnd, L"GetNetworkParams"); + ptrGetAdaptersInfo = (PtrGetAdaptersInfo)GetProcAddress(iphlpapiHnd, L"GetAdaptersInfo"); + ptrGetAdaptersAddresses = (PtrGetAdaptersAddresses)GetProcAddress(iphlpapiHnd, L"GetAdaptersAddresses"); + ptrGetNetworkParams = (PtrGetNetworkParams)GetProcAddress(iphlpapiHnd, L"GetNetworkParams"); #else ptrGetAdaptersInfo = (PtrGetAdaptersInfo)GetProcAddress(iphlpapiHnd, "GetAdaptersInfo"); ptrGetAdaptersAddresses = (PtrGetAdaptersAddresses)GetProcAddress(iphlpapiHnd, "GetAdaptersAddresses"); diff --git a/src/network/kernel/qnetworkproxy_win.cpp b/src/network/kernel/qnetworkproxy_win.cpp index 5fda228..7052bcc2 100644 --- a/src/network/kernel/qnetworkproxy_win.cpp +++ b/src/network/kernel/qnetworkproxy_win.cpp @@ -43,8 +43,6 @@ #ifndef QT_NO_NETWORKPROXY -#if defined(UNICODE) - #include #include #include @@ -269,15 +267,13 @@ void QWindowsSystemProxy::init() if (initialized) return; initialized = true; - if (QSysInfo::windowsVersion() & QSysInfo::WV_DOS_based) - return; // no point, this library is only available on 2k, XP and up #ifdef Q_OS_WINCE // Windows CE does not have any of the following API return; #else // load the winhttp.dll library - HINSTANCE winhttpHnd = LoadLibraryW(L"winhttp"); + HINSTANCE winhttpHnd = LoadLibrary(L"winhttp"); if (!winhttpHnd) return; // failed to load @@ -401,15 +397,6 @@ QList QNetworkProxyFactory::systemProxyForQuery(const QNetworkPro return parseServerList(query, sp->proxyServerList); } -#else // !UNICODE - -QList QNetworkProxyFactory::systemProxyForQuery(const QNetworkProxyQuery &) -{ - return QList() << QNetworkProxy::NoProxy; -} - -#endif - QT_END_NAMESPACE #endif diff --git a/src/network/socket/qlocalserver.cpp b/src/network/socket/qlocalserver.cpp index 05ef2e6..1a50dc4 100644 --- a/src/network/socket/qlocalserver.cpp +++ b/src/network/socket/qlocalserver.cpp @@ -78,8 +78,6 @@ QT_BEGIN_NAMESPACE to use it without one. In that case, you must use waitForNewConnection(), which blocks until either a connection is available or a timeout expires. - Note that this feature is not supported on Windows 9x. - \sa QLocalSocket, QTcpServer */ diff --git a/src/network/socket/qlocalserver_win.cpp b/src/network/socket/qlocalserver_win.cpp index 6af5ca5..c4f8f3c 100644 --- a/src/network/socket/qlocalserver_win.cpp +++ b/src/network/socket/qlocalserver_win.cpp @@ -62,9 +62,8 @@ bool QLocalServerPrivate::addListener() listeners << Listener(); Listener &listener = listeners.last(); - QT_WA({ - listener.handle = CreateNamedPipeW( - (TCHAR*)fullServerName.utf16(), // pipe name + listener.handle = CreateNamedPipe( + (const wchar_t *)fullServerName.utf16(), // pipe name PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, // read/write access PIPE_TYPE_MESSAGE | // message type pipe PIPE_READMODE_MESSAGE | // message-read mode @@ -74,19 +73,7 @@ bool QLocalServerPrivate::addListener() BUFSIZE, // input buffer size 3000, // client time-out NULL); - }, { - listener.handle = CreateNamedPipeA( - fullServerName.toLocal8Bit().constData(), // pipe name - PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, // read/write access - PIPE_TYPE_MESSAGE | // message type pipe - PIPE_READMODE_MESSAGE | // message-read mode - PIPE_WAIT, // blocking mode - PIPE_UNLIMITED_INSTANCES, // max. instances - BUFSIZE, // output buffer size - BUFSIZE, // input buffer size - 3000, // client time-out - NULL); - }); + if (listener.handle == INVALID_HANDLE_VALUE) { setError(QLatin1String("QLocalServerPrivate::addListener")); listeners.removeLast(); diff --git a/src/network/socket/qlocalsocket.cpp b/src/network/socket/qlocalsocket.cpp index acacdf2..c18026b 100644 --- a/src/network/socket/qlocalsocket.cpp +++ b/src/network/socket/qlocalsocket.cpp @@ -63,8 +63,6 @@ QT_BEGIN_NAMESPACE waitForReadyRead(), waitForBytesWritten(), and waitForDisconnected() which blocks until the operation is complete or the timeout expires. - Note that this feature is not supported on Window 9x. - \sa QLocalServer */ diff --git a/src/network/socket/qlocalsocket_win.cpp b/src/network/socket/qlocalsocket_win.cpp index 2b8d7e5..b1b69fc 100644 --- a/src/network/socket/qlocalsocket_win.cpp +++ b/src/network/socket/qlocalsocket_win.cpp @@ -137,25 +137,14 @@ void QLocalSocket::connectToServer(const QString &name, OpenMode openMode) forever { DWORD permissions = (openMode & QIODevice::ReadOnly) ? GENERIC_READ : 0; permissions |= (openMode & QIODevice::WriteOnly) ? GENERIC_WRITE : 0; - QT_WA({ - localSocket = CreateFileW( - (TCHAR*)d->fullServerName.utf16(), // pipe name - permissions, - 0, // no sharing - NULL, // default security attributes - OPEN_EXISTING, // opens existing pipe - FILE_FLAG_OVERLAPPED, - NULL); // no template file - }, { - localSocket = CreateFileA( - d->fullServerName.toLocal8Bit().constData(), // pipe name - permissions, - 0, // no sharing - NULL, // default security attributes - OPEN_EXISTING, // opens existing pipe - FILE_FLAG_OVERLAPPED, - NULL); // no template file - }); + localSocket = CreateFile((const wchar_t *)d->fullServerName.utf16(), // pipe name + permissions, + 0, // no sharing + NULL, // default security attributes + OPEN_EXISTING, // opens existing pipe + FILE_FLAG_OVERLAPPED, + NULL); // no template file + if (localSocket != INVALID_HANDLE_VALUE) break; DWORD error = GetLastError(); @@ -165,13 +154,8 @@ void QLocalSocket::connectToServer(const QString &name, OpenMode openMode) } // All pipe instances are busy, so wait until connected or up to 5 seconds. - QT_WA({ - if (!WaitNamedPipeW((TCHAR*)d->fullServerName.utf16(), 5000)) - break; - }, { - if (!WaitNamedPipeA(d->fullServerName.toLocal8Bit().constData(), 5000)) - break; - }); + if (!WaitNamedPipe((const wchar_t *)d->fullServerName.utf16(), 5000)) + break; } if (localSocket == INVALID_HANDLE_VALUE) { diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp index 59a3b60..ce8d810 100644 --- a/src/network/socket/qnativesocketengine_win.cpp +++ b/src/network/socket/qnativesocketengine_win.cpp @@ -918,15 +918,9 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxL int wsaRet = ::WSARecvFrom(socketDescriptor, &buf, 1, &bytesRead, &flags, (struct sockaddr *) &aa, &sz,0,0); if (wsaRet == SOCKET_ERROR) { int err = WSAGetLastError(); - if (err == WSAEMSGSIZE) { - // it is ok the buffer was to small if bytesRead is larger than - // maxLength (win 9x) then assume bytes read is really maxLenth - ret = qint64(bytesRead) > maxLength ? maxLength : qint64(bytesRead); - } else { - WS_ERROR_DEBUG(err); - setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString); - ret = -1; - } + WS_ERROR_DEBUG(err); + setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString); + ret = -1; } else { ret = qint64(bytesRead); } @@ -955,36 +949,32 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l qt_socket_setPortAndAddress(socketDescriptor, &sockAddrIPv4, &sockAddrIPv6, port, address, &sockAddrPtr, &sockAddrSize); - if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based && len > qint64(qt_socket_getMaxMsgSize(socketDescriptor))) { - // WSAEMSGSIZE is not reliable enough (win 9x) so we check max size our self. - setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString); - } else { - WSABUF buf; + WSABUF buf; #if !defined(Q_OS_WINCE) - buf.buf = len ? (char*)data : 0; + buf.buf = len ? (char*)data : 0; #else - char tmp; - buf.buf = len ? (char*)data : &tmp; + char tmp; + buf.buf = len ? (char*)data : &tmp; #endif - buf.len = len; - DWORD flags = 0; - DWORD bytesSent = 0; - if (::WSASendTo(socketDescriptor, &buf, 1, &bytesSent, flags, sockAddrPtr, sockAddrSize, 0,0) == SOCKET_ERROR) { - int err = WSAGetLastError(); - WS_ERROR_DEBUG(err); - switch (err) { - case WSAEMSGSIZE: - setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString); - break; - default: - setError(QAbstractSocket::NetworkError, SendDatagramErrorString); - break; - } - ret = -1; - } else { - ret = qint64(bytesSent); + buf.len = len; + DWORD flags = 0; + DWORD bytesSent = 0; + if (::WSASendTo(socketDescriptor, &buf, 1, &bytesSent, flags, sockAddrPtr, sockAddrSize, 0,0) == SOCKET_ERROR) { + int err = WSAGetLastError(); + WS_ERROR_DEBUG(err); + switch (err) { + case WSAEMSGSIZE: + setError(QAbstractSocket::DatagramTooLargeError, DatagramTooLargeErrorString); + break; + default: + setError(QAbstractSocket::NetworkError, SendDatagramErrorString); + break; } + ret = -1; + } else { + ret = qint64(bytesSent); } + #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QNativeSocketEnginePrivate::nativeSendDatagram(%p \"%s\", %li, \"%s\", %i) == %li", data, qt_prettyDebug(data, qMin(len, 16), len).data(), 0, address.toString().toLatin1().constData(), -- cgit v0.12 From d4a5ed717ae08034ffbc2377321406720a37bee9 Mon Sep 17 00:00:00 2001 From: miniak Date: Wed, 1 Jul 2009 11:50:01 +0200 Subject: src/opengl: Remove QT_WA and non-Unicode code paths, dropping Win9x and NT support Merge-request: 604 Reviewed-by: Marius Storm-Olsen --- src/opengl/qgl_win.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/opengl/qgl_win.cpp b/src/opengl/qgl_win.cpp index 40b0ce7..86dd1d8 100644 --- a/src/opengl/qgl_win.cpp +++ b/src/opengl/qgl_win.cpp @@ -642,14 +642,10 @@ public: QString windowClassName = qt_getRegisteredWndClass(); if (parent && !parent->internalWinId()) parent = parent->nativeParentWidget(); - QT_WA({ - const TCHAR *cname = (TCHAR*)windowClassName.utf16(); - dmy_id = CreateWindow(cname, 0, 0, 0, 0, 1, 1, - parent ? parent->winId() : 0, 0, qWinAppInst(), 0); - } , { - dmy_id = CreateWindowA(windowClassName.toLatin1(), 0, 0, 0, 0, 1, 1, - parent ? parent->winId() : 0, 0, qWinAppInst(), 0); - }); + + dmy_id = CreateWindow((const wchar_t *)windowClassName.utf16(), + 0, 0, 0, 0, 1, 1, + parent ? parent->winId() : 0, 0, qWinAppInst(), 0); dmy_pdc = GetDC(dmy_id); PIXELFORMATDESCRIPTOR dmy_pfd; -- cgit v0.12 From 5db6c3b72d3c28f55f14883767d29db3441b1b66 Mon Sep 17 00:00:00 2001 From: miniak Date: Wed, 1 Jul 2009 11:50:04 +0200 Subject: src/sql: Remove QT_WA and non-Unicode code paths, dropping Win9x and NT support Also remove many #ifdef UNICODE blocks Merge-request: 604 Reviewed-by: Marius Storm-Olsen --- src/sql/drivers/db2/qsql_db2.cpp | 30 +----------------------------- src/sql/drivers/odbc/qsql_odbc.cpp | 9 +-------- 2 files changed, 2 insertions(+), 37 deletions(-) diff --git a/src/sql/drivers/db2/qsql_db2.cpp b/src/sql/drivers/db2/qsql_db2.cpp index 1a82377..e4f564a 100644 --- a/src/sql/drivers/db2/qsql_db2.cpp +++ b/src/sql/drivers/db2/qsql_db2.cpp @@ -51,10 +51,6 @@ #include #include -#ifndef UNICODE -#define UNICODE -#endif - #if defined(Q_CC_BOR) // DB2's sqlsystm.h (included through sqlcli1.h) defines the SQL_BIGINT_TYPE // and SQL_BIGUINT_TYPE to wrong the types for Borland; so do the defines to @@ -111,22 +107,14 @@ public: static QString qFromTChar(SQLTCHAR* str) { -#ifdef UNICODE return QString::fromUtf16(str); -#else - return QString::fromLocal8Bit((const char*) str); -#endif } // dangerous!! (but fast). Don't use in functions that // require out parameters! static SQLTCHAR* qToTChar(const QString& str) { -#ifdef UNICODE return (SQLTCHAR*)str.utf16(); -#else - return (unsigned char*) str.ascii(); -#endif } static QString qWarnDB2Handle(int handleType, SQLHANDLE handle) @@ -347,12 +335,8 @@ static QString qGetStringData(SQLHANDLE hStmt, int column, int colSize, bool& is while (true) { r = SQLGetData(hStmt, - column+1, -#ifdef UNICODE + column + 1, SQL_C_WCHAR, -#else - SQL_C_CHAR, -#endif (SQLPOINTER)buf, colSize * sizeof(SQLTCHAR), &lengthIndicator); @@ -740,7 +724,6 @@ bool QDB2Result::exec() ind); break; } case QVariant::String: -#ifdef UNICODE { QString str(values.at(i).toString()); if (*ind != SQL_NULL_DATA) @@ -774,8 +757,6 @@ bool QDB2Result::exec() } break; } -#endif - // fall through default: { QByteArray ba = values.at(i).toString().toAscii(); int len = ba.length() + 1; @@ -849,12 +830,9 @@ bool QDB2Result::exec() case QVariant::ByteArray: break; case QVariant::String: -#ifdef UNICODE if (bindValueType(i) & QSql::Out) values[i] = QString::fromUtf16((ushort*)tmpStorage.takeFirst().constData()); break; -#endif - // fall through default: { values[i] = QString::fromAscii(tmpStorage.takeFirst().constData()); break; } @@ -1542,13 +1520,7 @@ bool QDB2Driver::hasFeature(DriverFeature f) const case FinishQuery: return true; case Unicode: - // this is the query that shows the codepage for the types: - // select typename, codepage from syscat.datatypes -#ifdef UNICODE return true; -#else - return false; -#endif } return false; } diff --git a/src/sql/drivers/odbc/qsql_odbc.cpp b/src/sql/drivers/odbc/qsql_odbc.cpp index af0c297..c48c7cd 100644 --- a/src/sql/drivers/odbc/qsql_odbc.cpp +++ b/src/sql/drivers/odbc/qsql_odbc.cpp @@ -1843,14 +1843,7 @@ void QODBCDriverPrivate::checkUnicode() unicode = false; return; #endif -#if defined(Q_WS_WIN) - QT_WA( - {}, - { - unicode = false; - return; - }) -#endif + SQLRETURN r; SQLUINTEGER fFunc; -- cgit v0.12 From 22ab94871c4a924e37eca720a1620da2e1a7259d Mon Sep 17 00:00:00 2001 From: miniak Date: Wed, 1 Jul 2009 11:50:07 +0200 Subject: src/activeqt: Remove QT_WA and non-Unicode code paths, dropping Win9x and NT support Also, buffer sizes passed to Registry APIs were incorrect. Merge-request: 604 Reviewed-by: Marius Storm-Olsen --- src/activeqt/container/qaxbase.cpp | 58 +++++------ src/activeqt/container/qaxdump.cpp | 4 +- src/activeqt/container/qaxobject.cpp | 4 - src/activeqt/container/qaxscript.cpp | 22 ++--- src/activeqt/container/qaxselect.cpp | 34 +++---- src/activeqt/container/qaxwidget.cpp | 56 +++++------ src/activeqt/control/qaxfactory.cpp | 12 +-- src/activeqt/control/qaxserver.cpp | 18 ++-- src/activeqt/control/qaxserverbase.cpp | 173 +++++++++------------------------ src/activeqt/control/qaxserverdll.cpp | 4 +- src/activeqt/control/qaxservermain.cpp | 15 +-- src/activeqt/shared/qaxtypes.cpp | 13 +-- 12 files changed, 147 insertions(+), 266 deletions(-) diff --git a/src/activeqt/container/qaxbase.cpp b/src/activeqt/container/qaxbase.cpp index 62dad6b..4fc9926 100644 --- a/src/activeqt/container/qaxbase.cpp +++ b/src/activeqt/container/qaxbase.cpp @@ -39,10 +39,6 @@ //#define QAX_NO_CLASSINFO -#ifndef UNICODE -#define UNICODE -#endif - #define QT_CHECK_STATE #include "qaxobject.h" @@ -174,7 +170,7 @@ inline DISPID QAxMetaObject::dispIDofName(const QByteArray &name, IDispatch *dis if (dispid == DISPID_UNKNOWN) { // get the Dispatch ID from the object QString unicodeName = QLatin1String(name); - OLECHAR *names = (TCHAR*)unicodeName.utf16(); + OLECHAR *names = (wchar_t*)unicodeName.utf16(); disp->GetIDsOfNames(IID_NULL, &names, 1, LOCALE_USER_DEFAULT, &dispid); if (dispid != DISPID_UNKNOWN) dispIDs.insert(name, dispid); @@ -638,7 +634,7 @@ QByteArray QAxEventSink::findProperty(DISPID dispID) UINT cNames; typeinfo->GetNames(dispID, &names, 1, &cNames); if (cNames) { - propname = QString::fromUtf16((const ushort *)names).toLatin1(); + propname = QString::fromWCharArray(names).toLatin1(); SysFreeString(names); } typeinfo->Release(); @@ -972,7 +968,7 @@ bool QAxBase::setControl(const QString &c) QUuid uuid(search); if (uuid.isNull()) { CLSID clsid; - HRESULT res = CLSIDFromProgID((WCHAR*)c.utf16(), &clsid); + HRESULT res = CLSIDFromProgID((wchar_t*)c.utf16(), &clsid); if (res == S_OK) search = QUuid(clsid).toString(); else { @@ -1137,7 +1133,7 @@ QStringList QAxBase::verbs() const while (enumVerbs->Next(1, &verb, &c) == S_OK) { if (!verb.lpszVerbName) continue; - QString verbName = QString::fromUtf16((const ushort *)verb.lpszVerbName); + QString verbName = QString::fromWCharArray(verb.lpszVerbName); if (!verbName.isEmpty()) d->verbs.insert(verbName, verb.lVerb); } @@ -1265,7 +1261,7 @@ bool QAxBase::initializeLicensedHelper(void *f, const QString &key, IUnknown **p } else if (licinfo.fRuntimeKeyAvail) { BSTR licenseKey; factory2->RequestLicKey(0, &licenseKey); - QString qlicenseKey = QString::fromUtf16((const ushort *)licenseKey); + QString qlicenseKey = QString::fromWCharArray(licenseKey); SysFreeString(licenseKey); qWarning("Use license key is '%s' to create object on unlicensed machine.", qlicenseKey.toLatin1().constData()); @@ -1275,7 +1271,7 @@ bool QAxBase::initializeLicensedHelper(void *f, const QString &key, IUnknown **p if (licinfo.fRuntimeKeyAvail) { BSTR licenseKey; factory2->RequestLicKey(0, &licenseKey); - QString qlicenseKey = QString::fromUtf16((const ushort *)licenseKey); + QString qlicenseKey = QString::fromWCharArray(licenseKey); SysFreeString(licenseKey); if (qlicenseKey != key) @@ -1435,7 +1431,7 @@ bool QAxBase::initializeRemote(IUnknown** ptr) serverInfo.dwReserved1 = 0; serverInfo.dwReserved2 = 0; serverInfo.pAuthInfo = &authInfo; - serverInfo.pwszName = (WCHAR*)server.utf16(); + serverInfo.pwszName = (wchar_t*)server.utf16(); IClassFactory *factory = 0; HRESULT res = CoGetClassObject(QUuid(clsid), CLSCTX_REMOTE_SERVER, &serverInfo, IID_IClassFactory, (void**)&factory); @@ -1747,7 +1743,7 @@ QMetaObject *qax_readInterfaceInfo(ITypeLib *typeLib, ITypeInfo *typeInfo, const if (S_OK != typeInfo->GetDocumentation(-1, &bstr, 0, 0, 0)) return 0; - className = QString::fromUtf16((const ushort *)bstr); + className = QString::fromWCharArray(bstr); SysFreeString(bstr); generator.readEnumInfo(); @@ -1768,7 +1764,7 @@ QMetaObject *qax_readClassInfo(ITypeLib *typeLib, ITypeInfo *classInfo, const QM if (S_OK != classInfo->GetDocumentation(-1, &bstr, 0, 0, 0)) return 0; - className = QString::fromUtf16((const ushort *)bstr); + className = QString::fromWCharArray(bstr); SysFreeString(bstr); generator.readEnumInfo(); @@ -1795,7 +1791,7 @@ QMetaObject *qax_readClassInfo(ITypeLib *typeLib, ITypeInfo *classInfo, const QM continue; interfaceInfo->GetDocumentation(-1, &bstr, 0, 0, 0); - QString interfaceName = QString::fromUtf16((const ushort *)bstr); + QString interfaceName = QString::fromWCharArray(bstr); SysFreeString(bstr); QByteArray key; @@ -1843,7 +1839,7 @@ MetaObjectGenerator::MetaObjectGenerator(ITypeLib *tlib, ITypeInfo *tinfo) typelib->AddRef(); BSTR bstr; typelib->GetDocumentation(-1, &bstr, 0, 0, 0); - current_typelib = QString::fromUtf16((const ushort *)bstr).toLatin1(); + current_typelib = QString::fromWCharArray(bstr).toLatin1(); SysFreeString(bstr); } readClassInfo(); @@ -1891,13 +1887,13 @@ QByteArray MetaObjectGenerator::usertypeToString(const TYPEDESC &tdesc, ITypeInf // get type library name BSTR typelibname = 0; usertypelib->GetDocumentation(-1, &typelibname, 0, 0, 0); - QByteArray typeLibName = QString::fromUtf16((const ushort *)typelibname).toLatin1(); + QByteArray typeLibName = QString::fromWCharArray(typelibname).toLatin1(); SysFreeString(typelibname); // get type name BSTR usertypename = 0; usertypelib->GetDocumentation(index, &usertypename, 0, 0, 0); - QByteArray userTypeName = QString::fromUtf16((const ushort *)usertypename).toLatin1(); + QByteArray userTypeName = QString::fromWCharArray(usertypename).toLatin1(); SysFreeString(usertypename); if (hasEnum(userTypeName)) // known enum? @@ -2287,7 +2283,7 @@ void MetaObjectGenerator::readEnumInfo() BSTR enumname; QByteArray enumName; if (typelib->GetDocumentation(i, &enumname, 0, 0, 0) == S_OK) { - enumName = QString::fromUtf16((const ushort *)enumname).toLatin1(); + enumName = QString::fromWCharArray(enumname).toLatin1(); SysFreeString(enumname); } else { enumName = "enum" + QByteArray::number(++enum_serial); @@ -2310,7 +2306,7 @@ void MetaObjectGenerator::readEnumInfo() UINT maxNamesOut; enuminfo->GetNames(memid, &valuename, 1, &maxNamesOut); if (maxNamesOut) { - valueName = QString::fromUtf16((const ushort *)valuename).toLatin1(); + valueName = QString::fromWCharArray(valuename).toLatin1(); SysFreeString(valuename); } else { valueName = "value" + QByteArray::number(valueindex++); @@ -2467,7 +2463,7 @@ void MetaObjectGenerator::readFuncsInfo(ITypeInfo *typeinfo, ushort nFuncs) QList names; int p; for (p = 0; p < (int)maxNamesOut; ++p) { - names << QString::fromUtf16((const ushort *)bstrNames[p]).toLatin1(); + names << QString::fromWCharArray(bstrNames[p]).toLatin1(); SysFreeString(bstrNames[p]); } @@ -2594,7 +2590,7 @@ void MetaObjectGenerator::readFuncsInfo(ITypeInfo *typeinfo, ushort nFuncs) // get function documentation BSTR bstrDocu; info->GetDocumentation(funcdesc->memid, 0, &bstrDocu, 0, 0); - QString strDocu = QString::fromUtf16((const ushort*)bstrDocu); + QString strDocu = QString::fromWCharArray(bstrDocu); SysFreeString(bstrDocu); if (!!strDocu) desc += '[' + strDocu + ']'; @@ -2641,7 +2637,7 @@ void MetaObjectGenerator::readVarsInfo(ITypeInfo *typeinfo, ushort nVars) QByteArray variableName; uint flags = 0; - variableName = QString::fromUtf16((const ushort *)bstrName).toLatin1(); + variableName = QString::fromWCharArray(bstrName).toLatin1(); SysFreeString(bstrName); // get variable type @@ -2677,7 +2673,7 @@ void MetaObjectGenerator::readVarsInfo(ITypeInfo *typeinfo, ushort nVars) // get function documentation BSTR bstrDocu; info->GetDocumentation(vardesc->memid, 0, &bstrDocu, 0, 0); - QString strDocu = QString::fromUtf16((const ushort*)bstrDocu); + QString strDocu = QString::fromWCharArray(bstrDocu); SysFreeString(bstrDocu); if (!!strDocu) desc += '[' + strDocu + ']'; @@ -2800,7 +2796,7 @@ void MetaObjectGenerator::readEventInterface(ITypeInfo *eventinfo, IConnectionPo QList names; int p; for (p = 0; p < (int)maxNamesOut; ++p) { - names << QString::fromUtf16((const ushort *)bstrNames[p]).toLatin1(); + names << QString::fromWCharArray(bstrNames[p]).toLatin1(); SysFreeString(bstrNames[p]); } @@ -2824,7 +2820,7 @@ void MetaObjectGenerator::readEventInterface(ITypeInfo *eventinfo, IConnectionPo // get function documentation BSTR bstrDocu; eventinfo->GetDocumentation(funcdesc->memid, 0, &bstrDocu, 0, 0); - QString strDocu = QString::fromUtf16((const ushort*)bstrDocu); + QString strDocu = QString::fromWCharArray(bstrDocu); SysFreeString(bstrDocu); if (!!strDocu) desc += '[' + strDocu + ']'; @@ -2982,7 +2978,7 @@ QMetaObject *MetaObjectGenerator::metaObject(const QMetaObject *parentObject, co if (typelib) { BSTR bstr; typelib->GetDocumentation(-1, &bstr, 0, 0, 0); - current_typelib = QString::fromUtf16((const ushort *)bstr).toLatin1(); + current_typelib = QString::fromWCharArray(bstr).toLatin1(); SysFreeString(bstr); } if (d->tryCache && tryCache()) @@ -3391,9 +3387,9 @@ static bool checkHRESULT(HRESULT hres, EXCEPINFO *exc, QAxBase *that, const QStr exc->pfnDeferredFillIn(exc); code = exc->wCode ? exc->wCode : exc->scode; - source = QString::fromUtf16((const ushort *)exc->bstrSource); - desc = QString::fromUtf16((const ushort *)exc->bstrDescription); - help = QString::fromUtf16((const ushort *)exc->bstrHelpFile); + source = QString::fromWCharArray(exc->bstrSource); + desc = QString::fromWCharArray(exc->bstrDescription); + help = QString::fromWCharArray(exc->bstrHelpFile); uint helpContext = exc->dwHelpContext; if (helpContext && !help.isEmpty()) @@ -4228,7 +4224,7 @@ public: if (!var) return E_POINTER; - QString property = QString::fromUtf16((const ushort *)name); + QString property = QString::fromWCharArray(name); QVariant qvar = map.value(property); QVariantToVARIANT(qvar, *var); return S_OK; @@ -4237,7 +4233,7 @@ public: { if (!var) return E_POINTER; - QString property = QString::fromUtf16((const ushort *)name); + QString property = QString::fromWCharArray(name); QVariant qvar = VARIANTToQVariant(*var, 0); map[property] = qvar; diff --git a/src/activeqt/container/qaxdump.cpp b/src/activeqt/container/qaxdump.cpp index 39d5121..a654a8f 100644 --- a/src/activeqt/container/qaxdump.cpp +++ b/src/activeqt/container/qaxdump.cpp @@ -66,8 +66,8 @@ QString qax_docuFromName(ITypeInfo *typeInfo, const QString &name) BSTR docStringBstr, helpFileBstr; ulong helpContext; HRESULT hres = typeInfo->GetDocumentation(memId, 0, &docStringBstr, &helpContext, &helpFileBstr); - QString docString = QString::fromUtf16((const ushort *)docStringBstr); - QString helpFile = QString::fromUtf16((const ushort *)helpFileBstr); + QString docString = QString::fromWCharArray(docStringBstr); + QString helpFile = QString::fromWCharArray(helpFileBstr); SysFreeString(docStringBstr); SysFreeString(helpFileBstr); if (hres == S_OK) { diff --git a/src/activeqt/container/qaxobject.cpp b/src/activeqt/container/qaxobject.cpp index 3526f93..412c5b5 100644 --- a/src/activeqt/container/qaxobject.cpp +++ b/src/activeqt/container/qaxobject.cpp @@ -37,10 +37,6 @@ ** ****************************************************************************/ -#ifndef UNICODE -#define UNICODE -#endif - #include "qaxobject.h" #ifndef QT_NO_WIN_ACTIVEQT diff --git a/src/activeqt/container/qaxscript.cpp b/src/activeqt/container/qaxscript.cpp index dcfc84b..2ee08b3 100644 --- a/src/activeqt/container/qaxscript.cpp +++ b/src/activeqt/container/qaxscript.cpp @@ -37,10 +37,6 @@ ** ****************************************************************************/ -#ifndef UNICODE -#define UNICODE -#endif - #include "qaxscript.h" #ifndef QT_NO_WIN_ACTIVEQT @@ -194,7 +190,7 @@ HRESULT WINAPI QAxScriptSite::GetItemInfo(LPCOLESTR pstrName, DWORD mask, IUnkno else if (mask & SCRIPTINFO_ITYPEINFO) return E_POINTER; - QAxBase *object = script->findObject(QString::fromUtf16((const ushort*)pstrName)); + QAxBase *object = script->findObject(QString::fromWCharArray(pstrName)); if (!object) return TYPE_E_ELEMENTNOTFOUND; @@ -236,9 +232,9 @@ HRESULT WINAPI QAxScriptSite::OnScriptTerminate(const VARIANT *result, const EXC emit script->finished(VARIANTToQVariant(*result, 0)); if (exception) emit script->finished(exception->wCode, - QString::fromUtf16((const ushort*)exception->bstrSource), - QString::fromUtf16((const ushort*)exception->bstrDescription), - QString::fromUtf16((const ushort*)exception->bstrHelpFile) + QString::fromWCharArray(exception->bstrSource), + QString::fromWCharArray(exception->bstrDescription), + QString::fromWCharArray(exception->bstrHelpFile) ); return S_OK; } @@ -287,14 +283,14 @@ HRESULT WINAPI QAxScriptSite::OnScriptError(IActiveScriptError *error) error->GetSourcePosition(&context, &lineNumber, &charPos); HRESULT hres = error->GetSourceLineText(&bstrLineText); if (hres == S_OK) { - lineText = QString::fromUtf16((const ushort*)bstrLineText); + lineText = QString::fromWCharArray(bstrLineText); SysFreeString(bstrLineText); } SysFreeString(exception.bstrSource); SysFreeString(exception.bstrDescription); SysFreeString(exception.bstrHelpFile); - emit script->error(exception.wCode, QString::fromUtf16((const ushort*)exception.bstrDescription), lineNumber, lineText); + emit script->error(exception.wCode, QString::fromWCharArray(exception.bstrDescription), lineNumber, lineText); return S_OK; } @@ -463,7 +459,7 @@ bool QAxScriptEngine::initialize(IUnknown **ptr) return false; CLSID clsid; - HRESULT hres = CLSIDFromProgID((WCHAR*)script_language.utf16(), &clsid); + HRESULT hres = CLSIDFromProgID((wchar_t*)script_language.utf16(), &clsid); if(FAILED(hres)) return false; @@ -609,7 +605,7 @@ void QAxScriptEngine::addItem(const QString &name) if (!engine) return; - engine->AddNamedItem((WCHAR*)name.utf16(), SCRIPTITEM_ISSOURCE|SCRIPTITEM_ISVISIBLE); + engine->AddNamedItem((wchar_t*)name.utf16(), SCRIPTITEM_ISSOURCE|SCRIPTITEM_ISVISIBLE); #endif } @@ -1173,7 +1169,7 @@ bool QAxScriptManager::registerEngine(const QString &name, const QString &extens return false; CLSID clsid; - HRESULT hres = CLSIDFromProgID((WCHAR*)name.utf16(), &clsid); + HRESULT hres = CLSIDFromProgID((wchar_t*)name.utf16(), &clsid); if (hres != S_OK) return false; diff --git a/src/activeqt/container/qaxselect.cpp b/src/activeqt/container/qaxselect.cpp index 5de39e4..a0c725d 100644 --- a/src/activeqt/container/qaxselect.cpp +++ b/src/activeqt/container/qaxselect.cpp @@ -52,54 +52,46 @@ public: : QAbstractListModel(parent) { HKEY classes_key; - QT_WA_INLINE( - RegOpenKeyExW(HKEY_CLASSES_ROOT, L"CLSID", 0, KEY_READ, &classes_key), - RegOpenKeyExA(HKEY_CLASSES_ROOT, "CLSID", 0, KEY_READ, &classes_key)); + RegOpenKeyEx(HKEY_CLASSES_ROOT, L"CLSID", 0, KEY_READ, &classes_key); if (!classes_key) return; DWORD index = 0; LONG result = 0; - TCHAR buffer[256]; - DWORD szBuffer = sizeof(buffer); + wchar_t buffer[256]; + DWORD szBuffer = sizeof(buffer) / sizeof(wchar_t); FILETIME ft; do { - result = QT_WA_INLINE( - RegEnumKeyExW(classes_key, index, (wchar_t*)&buffer, &szBuffer, 0, 0, 0, &ft), - RegEnumKeyExA(classes_key, index, (char*)&buffer, &szBuffer, 0, 0, 0, &ft)); - szBuffer = sizeof(buffer); + result = RegEnumKeyEx(classes_key, index, buffer, &szBuffer, 0, 0, 0, &ft); + szBuffer = sizeof(buffer) / sizeof(wchar_t); if (result == ERROR_SUCCESS) { HKEY sub_key; - QString clsid = QT_WA_INLINE(QString::fromUtf16((ushort*)buffer), QString::fromLocal8Bit((char*)buffer)); - result = QT_WA_INLINE( - RegOpenKeyExW(classes_key, reinterpret_cast(QString(clsid + "\\Control").utf16()), 0, KEY_READ, &sub_key), - RegOpenKeyA(classes_key, QString(clsid + QLatin1String("\\Control")).toLocal8Bit(), &sub_key)); + QString clsid = QString::fromWCharArray(buffer); + result = RegOpenKeyEx(classes_key, reinterpret_cast(QString(clsid + "\\Control").utf16()), 0, KEY_READ, &sub_key); if (result == ERROR_SUCCESS) { RegCloseKey(sub_key); - QT_WA_INLINE( - RegistryQueryValueW(classes_key, buffer, (LPBYTE)buffer, &szBuffer), - RegQueryValueA(classes_key, (char*)buffer, (char*)buffer, (LONG*)&szBuffer)); - QString name = QT_WA_INLINE(QString::fromUtf16((ushort*)buffer, szBuffer / sizeof(TCHAR)) , QString::fromLocal8Bit((char*)buffer, szBuffer)); + RegistryQueryValue(classes_key, buffer, (LPBYTE)buffer, &szBuffer); + QString name = QString::fromWCharArray(buffer); controls << name; clsids.insert(name, clsid); } result = ERROR_SUCCESS; } - szBuffer = sizeof(buffer); + szBuffer = sizeof(buffer) / sizeof(wchar_t); ++index; } while (result == ERROR_SUCCESS); RegCloseKey(classes_key); controls.sort(); } - LONG RegistryQueryValueW(HKEY hKey, LPCWSTR lpSubKey, LPBYTE lpData, LPDWORD lpcbData) + LONG RegistryQueryValue(HKEY hKey, LPCWSTR lpSubKey, LPBYTE lpData, LPDWORD lpcbData) { LONG ret = ERROR_FILE_NOT_FOUND; HKEY hSubKey = NULL; - RegOpenKeyExW(hKey, lpSubKey, 0, KEY_READ, &hSubKey); + RegOpenKeyEx(hKey, lpSubKey, 0, KEY_READ, &hSubKey); if (hSubKey) { - ret = RegQueryValueExW(hSubKey, 0, 0, 0, lpData, lpcbData); + ret = RegQueryValueEx(hSubKey, 0, 0, 0, lpData, lpcbData); RegCloseKey(hSubKey); } return ret; diff --git a/src/activeqt/container/qaxwidget.cpp b/src/activeqt/container/qaxwidget.cpp index ebec872..615887f 100644 --- a/src/activeqt/container/qaxwidget.cpp +++ b/src/activeqt/container/qaxwidget.cpp @@ -37,11 +37,6 @@ ** ****************************************************************************/ -#ifndef UNICODE -#define UNICODE -#endif - - #include "qaxwidget.h" #ifndef QT_NO_WIN_ACTIVEQT @@ -470,7 +465,7 @@ static QAbstractEventDispatcher::EventFilter previous_filter = 0; #if defined(Q_WS_WINCE) static int filter_ref = 0; #else -static const char *qaxatom = "QAxContainer4_Atom"; +static const wchar_t *qaxatom = L"QAxContainer4_Atom"; #endif // The filter procedure listening to user interaction on the control @@ -714,7 +709,7 @@ bool QAxClientSite::activateObject(bool initialized, const QByteArray &data) BSTR userType; HRESULT result = m_spOleObject->GetUserType(USERCLASSTYPE_SHORT, &userType); if (result == S_OK) { - widget->setWindowTitle(QString::fromUtf16((const ushort *)userType)); + widget->setWindowTitle(QString::fromWCharArray(userType)); CoTaskMemFree(userType); } } else { @@ -984,10 +979,7 @@ HRESULT WINAPI QAxClientSite::TranslateAccelerator(LPMSG lpMsg, DWORD /*grfModif eventTranslated = false; if (lpMsg->message == WM_KEYDOWN && !lpMsg->wParam) return S_OK; - QT_WA_INLINE( - SendMessage(host->winId(), lpMsg->message, lpMsg->wParam, lpMsg->lParam), - SendMessageA(host->winId(), lpMsg->message, lpMsg->wParam, lpMsg->lParam) - ); + SendMessage(host->winId(), lpMsg->message, lpMsg->wParam, lpMsg->lParam); return S_OK; } @@ -1173,15 +1165,15 @@ HRESULT WINAPI QAxClientSite::InsertMenus(HMENU /*hmenuShared*/, LPOLEMENUGROUPW #endif } -static int menuItemEntry(HMENU menu, int index, MENUITEMINFOA item, QString &text, QPixmap &/*icon*/) +static int menuItemEntry(HMENU menu, int index, MENUITEMINFO item, QString &text, QPixmap &/*icon*/) { if (item.fType == MFT_STRING && item.cch) { - char *titlebuf = new char[item.cch+1]; + wchar_t *titlebuf = new wchar_t[item.cch + 1]; item.dwTypeData = titlebuf; item.cch++; - ::GetMenuItemInfoA(menu, index, true, &item); - text = QString::fromLocal8Bit(titlebuf); - delete []titlebuf; + ::GetMenuItemInfo(menu, index, true, &item); + text = QString::fromWCharArray(titlebuf); + delete [] titlebuf; return MFT_STRING; } #if 0 @@ -1191,7 +1183,7 @@ static int menuItemEntry(HMENU menu, int index, MENUITEMINFOA item, QString &tex GetBitmapDimensionEx(hbm, &bmsize); QPixmap pixmap(1,1); QSize sz(MAP_LOGHIM_TO_PIX(bmsize.cx, pixmap.logicalDpiX()), - MAP_LOGHIM_TO_PIX(bmsize.cy, pixmap.logicalDpiY())); + MAP_LOGHIM_TO_PIX(bmsize.cy, pixmap.logicalDpiY())); pixmap.resize(bmsize.cx, bmsize.cy); if (!pixmap.isNull()) { @@ -1215,11 +1207,11 @@ QMenu *QAxClientSite::generatePopup(HMENU subMenu, QWidget *parent) if (count) popup = new QMenu(parent); for (int i = 0; i < count; ++i) { - MENUITEMINFOA item; - memset(&item, 0, sizeof(MENUITEMINFOA)); - item.cbSize = sizeof(MENUITEMINFOA); + MENUITEMINFO item; + memset(&item, 0, sizeof(MENUITEMINFO)); + item.cbSize = sizeof(MENUITEMINFO); item.fMask = MIIM_ID | MIIM_TYPE | MIIM_SUBMENU; - ::GetMenuItemInfoA(subMenu, i, true, &item); + ::GetMenuItemInfo(subMenu, i, true, &item); QAction *action = 0; QMenu *popupMenu = 0; @@ -1295,11 +1287,11 @@ HRESULT WINAPI QAxClientSite::SetMenu(HMENU hmenuShared, HOLEMENU holemenu, HWND int count = GetMenuItemCount(hmenuShared); for (int i = 0; i < count; ++i) { - MENUITEMINFOA item; - memset(&item, 0, sizeof(MENUITEMINFOA)); - item.cbSize = sizeof(MENUITEMINFOA); + MENUITEMINFO item; + memset(&item, 0, sizeof(MENUITEMINFO)); + item.cbSize = sizeof(MENUITEMINFO); item.fMask = MIIM_ID | MIIM_TYPE | MIIM_SUBMENU; - ::GetMenuItemInfoA(hmenuShared, i, true, &item); + ::GetMenuItemInfo(hmenuShared, i, true, &item); QAction *action = 0; QMenu *popupMenu = 0; @@ -1379,7 +1371,7 @@ int QAxClientSite::qt_metacall(QMetaObject::Call call, int isignal, void **argv) OleMenuItem oleItem = menuItemMap.value(action); if (oleItem.hMenu) - ::PostMessageA(m_menuOwner, WM_COMMAND, oleItem.id, 0); + ::PostMessage(m_menuOwner, WM_COMMAND, oleItem.id, 0); return -1; #endif } @@ -1404,7 +1396,7 @@ HRESULT WINAPI QAxClientSite::RemoveMenus(HMENU /*hmenuShared*/) HRESULT WINAPI QAxClientSite::SetStatusText(LPCOLESTR pszStatusText) { - QStatusTipEvent tip(QString::fromUtf16((const ushort *)(BSTR)pszStatusText)); + QStatusTipEvent tip(QString::fromWCharArray(pszStatusText)); QApplication::sendEvent(widget, &tip); return S_OK; } @@ -1513,7 +1505,7 @@ HRESULT WINAPI QAxClientSite::SetActiveObject(IOleInPlaceActiveObject *pActiveOb AX_DEBUG(QAxClientSite::SetActiveObject); if (pszObjName && widget) - widget->setWindowTitle(QString::fromUtf16((const ushort *)(BSTR)pszObjName)); + widget->setWindowTitle(QString::fromWCharArray(pszObjName)); if (m_spInPlaceActiveObject) { if (!inPlaceModelessEnabled) @@ -1952,12 +1944,12 @@ bool QAxWidget::createHostWindow(bool initialized, const QByteArray &data) container->activateObject(initialized, data); #if !defined(Q_OS_WINCE) - ATOM filter_ref = FindAtomA(qaxatom); + ATOM filter_ref = FindAtom(qaxatom); #endif if (!filter_ref) previous_filter = QAbstractEventDispatcher::instance()->setEventFilter(axc_FilterProc); #if !defined(Q_OS_WINCE) - AddAtomA(qaxatom); + AddAtom(qaxatom); #else ++filter_ref; #endif @@ -1992,10 +1984,10 @@ void QAxWidget::clear() return; if (!control().isEmpty()) { #if !defined(Q_OS_WINCE) - ATOM filter_ref = FindAtomA(qaxatom); + ATOM filter_ref = FindAtom(qaxatom); if (filter_ref) DeleteAtom(filter_ref); - filter_ref = FindAtomA(qaxatom); + filter_ref = FindAtom(qaxatom); if (!filter_ref) { #else if (!filter_ref && !--filter_ref) { diff --git a/src/activeqt/control/qaxfactory.cpp b/src/activeqt/control/qaxfactory.cpp index c65fbb8..742e93e 100644 --- a/src/activeqt/control/qaxfactory.cpp +++ b/src/activeqt/control/qaxfactory.cpp @@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE -extern char qAxModuleFilename[MAX_PATH]; +extern wchar_t qAxModuleFilename[MAX_PATH]; /*! \class QAxFactory @@ -277,7 +277,7 @@ bool QAxFactory::validateLicenseKey(const QString &key, const QString &licenseKe return true; if (licenseKey.isEmpty()) { - QString licFile(QFile::decodeName(qAxModuleFilename)); + QString licFile(QString::fromWCharArray(qAxModuleFilename)); int lastDot = licFile.lastIndexOf(QLatin1Char('.')); licFile = licFile.left(lastDot) + QLatin1String(".lic"); if (QFile::exists(licFile)) @@ -360,7 +360,7 @@ bool QAxFactory::isServer() return qAxIsServer; } -extern char qAxModuleFilename[MAX_PATH]; +extern wchar_t qAxModuleFilename[MAX_PATH]; /*! Returns the directory that contains the server binary. @@ -372,7 +372,7 @@ extern char qAxModuleFilename[MAX_PATH]; */ QString QAxFactory::serverDirPath() { - return QFileInfo(QString::fromLocal8Bit(qAxModuleFilename)).absolutePath(); + return QFileInfo(QString::fromWCharArray(qAxModuleFilename)).absolutePath(); } /*! @@ -384,7 +384,7 @@ QString QAxFactory::serverDirPath() */ QString QAxFactory::serverFilePath() { - return QString::fromLocal8Bit(qAxModuleFilename); + return QString::fromWCharArray(qAxModuleFilename); } /*! @@ -492,7 +492,7 @@ bool QAxFactory::registerActiveObject(QObject *object) if (qstricmp(object->metaObject()->classInfo(object->metaObject()->indexOfClassInfo("RegisterObject")).value(), "yes")) return false; - if (!QString::fromLocal8Bit(qAxModuleFilename).toLower().endsWith(QLatin1String(".exe"))) + if (!QString::fromWCharArray(qAxModuleFilename).toLower().endsWith(QLatin1String(".exe"))) return false; ActiveObject *active = new ActiveObject(object, qAxFactory()); diff --git a/src/activeqt/control/qaxserver.cpp b/src/activeqt/control/qaxserver.cpp index a9b3271..e6b0c17 100644 --- a/src/activeqt/control/qaxserver.cpp +++ b/src/activeqt/control/qaxserver.cpp @@ -63,7 +63,7 @@ QT_BEGIN_NAMESPACE bool qAxIsServer = false; HANDLE qAxInstance = 0; ITypeLib *qAxTypeLibrary = 0; -char qAxModuleFilename[MAX_PATH]; +wchar_t qAxModuleFilename[MAX_PATH]; bool qAxOutProcServer = false; // The QAxFactory instance @@ -116,19 +116,19 @@ QString qAxInit() InitializeCriticalSection(&qAxModuleSection); - libFile = QString::fromLocal8Bit(qAxModuleFilename); + libFile = QString::fromWCharArray(qAxModuleFilename); libFile = libFile.toLower(); - if (LoadTypeLibEx((TCHAR*)libFile.utf16(), REGKIND_NONE, &qAxTypeLibrary) == S_OK) + if (LoadTypeLibEx((wchar_t*)libFile.utf16(), REGKIND_NONE, &qAxTypeLibrary) == S_OK) return libFile; int lastDot = libFile.lastIndexOf(QLatin1Char('.')); libFile = libFile.left(lastDot) + QLatin1String(".tlb"); - if (LoadTypeLibEx((TCHAR*)libFile.utf16(), REGKIND_NONE, &qAxTypeLibrary) == S_OK) + if (LoadTypeLibEx((wchar_t*)libFile.utf16(), REGKIND_NONE, &qAxTypeLibrary) == S_OK) return libFile; lastDot = libFile.lastIndexOf(QLatin1Char('.')); libFile = libFile.left(lastDot) + QLatin1String(".olb"); - if (LoadTypeLibEx((TCHAR*)libFile.utf16(), REGKIND_NONE, &qAxTypeLibrary) == S_OK) + if (LoadTypeLibEx((wchar_t*)libFile.utf16(), REGKIND_NONE, &qAxTypeLibrary) == S_OK) return libFile; libFile = QString(); @@ -207,7 +207,7 @@ QString qax_clean_type(const QString &type, const QMetaObject *mo) HRESULT UpdateRegistry(BOOL bRegister) { qAxIsServer = false; - QString file = QString::fromLocal8Bit(qAxModuleFilename); + QString file = QString::fromWCharArray(qAxModuleFilename); QString path = file.left(file.lastIndexOf(QLatin1Char('\\'))+1); QString module = file.right(file.length() - path.length()); module = module.left(module.lastIndexOf(QLatin1Char('.'))); @@ -229,7 +229,7 @@ HRESULT UpdateRegistry(BOOL bRegister) typeLibVersion = QString::number((uint)major) + QLatin1Char('.') + QString::number((uint)minor); if (bRegister) - RegisterTypeLib(qAxTypeLibrary, (TCHAR*)libFile.utf16(), 0); + RegisterTypeLib(qAxTypeLibrary, (wchar_t*)libFile.utf16(), 0); else UnRegisterTypeLib(libAttr->guid, libAttr->wMajorVerNum, libAttr->wMinorVerNum, libAttr->lcid, libAttr->syskind); @@ -1071,7 +1071,7 @@ extern "C" HRESULT __stdcall DumpIDL(const QString &outfile, const QString &ver) QFile file(outfile); file.remove(); - QString filebase = QString::fromLocal8Bit(qAxModuleFilename); + QString filebase = QString::fromWCharArray(qAxModuleFilename); filebase = filebase.left(filebase.lastIndexOf(QLatin1Char('.'))); QString appID = qAxFactory()->appID().toString().toUpper(); @@ -1107,7 +1107,7 @@ extern "C" HRESULT __stdcall DumpIDL(const QString &outfile, const QString &ver) out << "/****************************************************************************" << endl; out << "** Interface definition generated for ActiveQt project" << endl; out << "**" << endl; - out << "** '" << qAxModuleFilename << '\'' << endl; + out << "** '" << QString::fromWCharArray(qAxModuleFilename) << '\'' << endl; out << "**" << endl; out << "** Created: " << QDateTime::currentDateTime().toString() << endl; out << "**" << endl; diff --git a/src/activeqt/control/qaxserverbase.cpp b/src/activeqt/control/qaxserverbase.cpp index 2cac004..d7a8e07 100644 --- a/src/activeqt/control/qaxserverbase.cpp +++ b/src/activeqt/control/qaxserverbase.cpp @@ -788,17 +788,9 @@ bool qax_winEventFilter(void *message) QAxServerBase *axbase = 0; while (!axbase && baseHwnd) { #ifdef GWLP_USERDATA - QT_WA({ - axbase = (QAxServerBase*)GetWindowLongPtrW(baseHwnd, GWLP_USERDATA); - }, { - axbase = (QAxServerBase*)GetWindowLongPtrA(baseHwnd, GWLP_USERDATA); - }); + axbase = (QAxServerBase*)GetWindowLongPtr(baseHwnd, GWLP_USERDATA); #else - QT_WA({ - axbase = (QAxServerBase*)GetWindowLongW(baseHwnd, GWL_USERDATA); - }, { - axbase = (QAxServerBase*)GetWindowLongA(baseHwnd, GWL_USERDATA); - }); + axbase = (QAxServerBase*)GetWindowLong(baseHwnd, GWL_USERDATA); #endif baseHwnd = ::GetParent(baseHwnd); @@ -905,11 +897,7 @@ public: // hook into eventloop; this allows a server to create his own QApplication object if (!qax_hhook && qax_ownQApp) { - QT_WA({ - qax_hhook = SetWindowsHookExW(WH_GETMESSAGE, axs_FilterProc, 0, GetCurrentThreadId()); - }, { - qax_hhook = SetWindowsHookExA(WH_GETMESSAGE, axs_FilterProc, 0, GetCurrentThreadId()); - }); + qax_hhook = SetWindowsHookEx(WH_GETMESSAGE, axs_FilterProc, 0, GetCurrentThreadId()); } HRESULT res; @@ -983,7 +971,7 @@ public: HRESULT WINAPI CreateInstanceLic(IUnknown *pUnkOuter, IUnknown *pUnkReserved, REFIID iid, BSTR bKey, PVOID *ppObject) { - QString licenseKey = QString::fromUtf16((const ushort *)bKey); + QString licenseKey = QString::fromWCharArray(bKey); if (!qAxFactory()->validateLicenseKey(className, licenseKey)) return CLASS_E_NOTLICENSED; return CreateInstanceHelper(pUnkOuter, iid, ppObject); @@ -1303,15 +1291,11 @@ bool QAxServerBase::internalCreate() internalBind(); if (isWidget) { - if (!stayTopLevel) { - QEvent e(QEvent::EmbeddingControl); - QApplication::sendEvent(qt.widget, &e); - QT_WA({ - ::SetWindowLongW(qt.widget->winId(), GWL_STYLE, WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); - }, { - ::SetWindowLongA(qt.widget->winId(), GWL_STYLE, WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); - }); - } + if (!stayTopLevel) { + QEvent e(QEvent::EmbeddingControl); + QApplication::sendEvent(qt.widget, &e); + ::SetWindowLong(qt.widget->winId(), GWL_STYLE, WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); + } qt.widget->setAttribute(Qt::WA_QuitOnClose, false); qt.widget->move(0, 0); @@ -1368,52 +1352,26 @@ class HackWidget : public QWidget LRESULT CALLBACK QAxServerBase::ActiveXProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { if (uMsg == WM_CREATE) { - QAxServerBase *that; - QT_WA({ - CREATESTRUCTW *cs = (CREATESTRUCTW*)lParam; - that = (QAxServerBase*)cs->lpCreateParams; - }, { - CREATESTRUCTA *cs = (CREATESTRUCTA*)lParam; - that = (QAxServerBase*)cs->lpCreateParams; - }); + CREATESTRUCT *cs = (CREATESTRUCT*)lParam; + QAxServerBase *that = (QAxServerBase*)cs->lpCreateParams; #ifdef GWLP_USERDATA - QT_WA({ - SetWindowLongPtrW(hWnd, GWLP_USERDATA, (LONG_PTR)that); - }, { - SetWindowLongPtrA(hWnd, GWLP_USERDATA, (LONG_PTR)that); - }); + SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)that); #else - QT_WA({ - SetWindowLongW(hWnd, GWL_USERDATA, (LONG)that); - }, { - SetWindowLongA(hWnd, GWL_USERDATA, (LONG)that); - }); + SetWindowLong(hWnd, GWL_USERDATA, (LONG)that); #endif - that->m_hWnd = hWnd; + that->m_hWnd = hWnd; - QT_WA({ - return ::DefWindowProcW(hWnd, uMsg, wParam, lParam); - }, { - return ::DefWindowProcA(hWnd, uMsg, wParam, lParam); - }); + return ::DefWindowProc(hWnd, uMsg, wParam, lParam); } QAxServerBase *that = 0; #ifdef GWLP_USERDATA - QT_WA({ - that = (QAxServerBase*)GetWindowLongPtrW(hWnd, GWLP_USERDATA); - }, { - that = (QAxServerBase*)GetWindowLongPtrA(hWnd, GWLP_USERDATA); - }); + that = (QAxServerBase*)GetWindowLongPtr(hWnd, GWLP_USERDATA); #else - QT_WA({ - that = (QAxServerBase*)GetWindowLongW(hWnd, GWL_USERDATA); - }, { - that = (QAxServerBase*)GetWindowLongA(hWnd, GWL_USERDATA); - }); + that = (QAxServerBase*)GetWindowLong(hWnd, GWL_USERDATA); #endif if (that) { @@ -1563,11 +1521,7 @@ LRESULT CALLBACK QAxServerBase::ActiveXProc(HWND hWnd, UINT uMsg, WPARAM wParam, } } - QT_WA({ - return ::DefWindowProcW(hWnd, uMsg, wParam, lParam); - }, { - return ::DefWindowProcA(hWnd, uMsg, wParam, lParam); - }); + return ::DefWindowProc(hWnd, uMsg, wParam, lParam); } /*! @@ -1583,54 +1537,29 @@ HWND QAxServerBase::create(HWND hWndParent, RECT& rcPos) QString cn(QLatin1String("QAxControl")); cn += QString::number((int)ActiveXProc); if (!atom) { - QT_WA({ - WNDCLASSW wcTemp; - wcTemp.style = CS_DBLCLKS; - wcTemp.cbClsExtra = 0; - wcTemp.cbWndExtra = 0; - wcTemp.hbrBackground = 0; - wcTemp.hCursor = 0; - wcTemp.hIcon = 0; - wcTemp.hInstance = hInst; - wcTemp.lpszClassName = (wchar_t*)cn.utf16(); - wcTemp.lpszMenuName = 0; - wcTemp.lpfnWndProc = ActiveXProc; - - atom = RegisterClassW(&wcTemp); - }, { - QByteArray cna = cn.toLatin1(); - WNDCLASSA wcTemp; - wcTemp.style = CS_DBLCLKS; - wcTemp.cbClsExtra = 0; - wcTemp.cbWndExtra = 0; - wcTemp.hbrBackground = 0; - wcTemp.hCursor = 0; - wcTemp.hIcon = 0; - wcTemp.hInstance = hInst; - wcTemp.lpszClassName = cna.data(); - wcTemp.lpszMenuName = 0; - wcTemp.lpfnWndProc = ActiveXProc; - - atom = RegisterClassA(&wcTemp); - }); + WNDCLASS wcTemp; + wcTemp.style = CS_DBLCLKS; + wcTemp.cbClsExtra = 0; + wcTemp.cbWndExtra = 0; + wcTemp.hbrBackground = 0; + wcTemp.hCursor = 0; + wcTemp.hIcon = 0; + wcTemp.hInstance = hInst; + wcTemp.lpszClassName = (wchar_t*)cn.utf16(); + wcTemp.lpszMenuName = 0; + wcTemp.lpfnWndProc = ActiveXProc; + + atom = RegisterClass(&wcTemp); } LeaveCriticalSection(&createWindowSection); if (!atom && GetLastError() != ERROR_CLASS_ALREADY_EXISTS) return 0; Q_ASSERT(!m_hWnd); - HWND hWnd = 0; - QT_WA({ - hWnd = ::CreateWindowW((wchar_t*)cn.utf16(), 0, - WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, - rcPos.left, rcPos.top, rcPos.right - rcPos.left, - rcPos.bottom - rcPos.top, hWndParent, 0, hInst, this); - }, { - hWnd = ::CreateWindowA(cn.toLatin1().data(), 0, - WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, - rcPos.left, rcPos.top, rcPos.right - rcPos.left, - rcPos.bottom - rcPos.top, hWndParent, 0, hInst, this); - }); + HWND hWnd = ::CreateWindow((wchar_t*)cn.utf16(), 0, + WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, + rcPos.left, rcPos.top, rcPos.right - rcPos.left, + rcPos.bottom - rcPos.top, hWndParent, 0, hInst, this); Q_ASSERT(m_hWnd == hWnd); @@ -1676,11 +1605,7 @@ HMENU QAxServerBase::createPopup(QMenu *popup, HMENU oldMenu) actionMap.remove(itemId); actionMap.insert(itemId, action); } - QT_WA({ - AppendMenuW(popupMenu, flags, itemId, (TCHAR*)action->text().utf16()); - }, { - AppendMenuA(popupMenu, flags, itemId, action->text().toLocal8Bit()); - }); + AppendMenu(popupMenu, flags, itemId, (const wchar_t *)action->text().utf16()); } if (oldMenu) DrawMenuBar(hwndMenuOwner); @@ -1726,11 +1651,7 @@ void QAxServerBase::createMenu(QMenuBar *menuBar) itemId = static_cast(reinterpret_cast(action)); actionMap.insert(itemId, action); } - QT_WA({ - AppendMenuW(hmenuShared, flags, itemId, (TCHAR*)action->text().utf16()); - } , { - AppendMenuA(hmenuShared, flags, itemId, action->text().toLocal8Bit()); - }); + AppendMenu(hmenuShared, flags, itemId, (const wchar_t *)action->text().utf16()); } OLEMENUGROUPWIDTHS menuWidths = {0,edit,0,object,0,help}; @@ -2397,7 +2318,7 @@ HRESULT WINAPI QAxServerBase::Invoke(DISPID dispidMember, REFIID riid, if (!cname) return res; - name = QString::fromUtf16((const ushort *)bname).toLatin1(); + name = QString::fromWCharArray(bname).toLatin1(); SysFreeString(bname); } } @@ -2799,7 +2720,7 @@ HRESULT WINAPI QAxServerBase::Load(IStream *pStm) bool openAsText = false; QByteArray qtarray; if (hres == S_OK) { - QString streamName = QString::fromUtf16((const ushort *)stat.pwcsName); + QString streamName = QString::fromWCharArray(stat.pwcsName); CoTaskMemFree(stat.pwcsName); openAsText = streamName == QLatin1String("SomeStreamName"); if (stat.cbSize.HighPart) // more than 4GB - too large! @@ -2940,7 +2861,7 @@ HRESULT WINAPI QAxServerBase::Load(IStorage *pStg) */ streamName += QLatin1String("_Stream4.2"); - pStg->OpenStream((const WCHAR *)streamName.utf16(), 0, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &spStream); + pStg->OpenStream((const wchar_t *)streamName.utf16(), 0, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &spStream); if (!spStream) // support for streams saved with 4.1 and earlier pStg->OpenStream(L"SomeStreamName", 0, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &spStream); if (!spStream) @@ -2963,7 +2884,7 @@ HRESULT WINAPI QAxServerBase::Save(IStorage *pStg, BOOL fSameAsLoad) */ streamName += QLatin1String("_Stream4.2"); - pStg->CreateStream((const WCHAR *)streamName.utf16(), STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &spStream); + pStg->CreateStream((const wchar_t *)streamName.utf16(), STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &spStream); if (!spStream) return E_FAIL; @@ -3079,7 +3000,7 @@ HRESULT WINAPI QAxServerBase::SaveCompleted(LPCOLESTR fileName) if (qt.object->metaObject()->indexOfClassInfo("MIME") == -1) return E_NOTIMPL; - currentFileName = QString::fromUtf16(reinterpret_cast(fileName)); + currentFileName = QString::fromWCharArray(fileName); return S_OK; } @@ -3097,7 +3018,7 @@ HRESULT WINAPI QAxServerBase::GetCurFile(LPOLESTR *currentFile) if (!malloc) return E_OUTOFMEMORY; - *currentFile = static_cast(malloc->Alloc(currentFileName.length() * 2)); + *currentFile = static_cast(malloc->Alloc(currentFileName.length() * 2)); malloc->Release(); memcpy(*currentFile, currentFileName.unicode(), currentFileName.length() * 2); @@ -3117,7 +3038,7 @@ HRESULT WINAPI QAxServerBase::Load(LPCOLESTR fileName, DWORD mode) return E_NOTIMPL; } - QString loadFileName = QString::fromUtf16(reinterpret_cast(fileName)); + QString loadFileName = QString::fromWCharArray(fileName); QString fileExtension = loadFileName.mid(loadFileName.lastIndexOf(QLatin1Char('.')) + 1); QFile file(loadFileName); @@ -3162,7 +3083,7 @@ HRESULT WINAPI QAxServerBase::Save(LPCOLESTR fileName, BOOL fRemember) return E_NOTIMPL; } - QString saveFileName = QString::fromUtf16(reinterpret_cast(fileName)); + QString saveFileName = QString::fromWCharArray(fileName); QString fileExtension = saveFileName.mid(saveFileName.lastIndexOf(QLatin1Char('.')) + 1); QFile file(saveFileName); @@ -3220,7 +3141,7 @@ HRESULT WINAPI QAxServerBase::Draw(DWORD dwAspect, LONG lindex, void *pvAspect, bool bDeleteDC = false; if (!hicTargetDev) { - hicTargetDev = ::CreateDCA("DISPLAY", NULL, NULL, NULL); + hicTargetDev = ::CreateDC(L"DISPLAY", NULL, NULL, NULL); bDeleteDC = (hicTargetDev != hdcDraw); } @@ -3383,7 +3304,7 @@ HRESULT WINAPI QAxServerBase::OnAmbientPropertyChange(DISPID dispID) case DISPID_AMBIENT_DISPLAYNAME: if (var.vt != VT_BSTR || !isWidget) break; - qt.widget->setWindowTitle(QString::fromUtf16((const ushort *)var.bstrVal)); + qt.widget->setWindowTitle(QString::fromWCharArray(var.bstrVal)); break; case DISPID_AMBIENT_FONT: if (var.vt != VT_DISPATCH || !isWidget) diff --git a/src/activeqt/control/qaxserverdll.cpp b/src/activeqt/control/qaxserverdll.cpp index 375028d..512c408 100644 --- a/src/activeqt/control/qaxserverdll.cpp +++ b/src/activeqt/control/qaxserverdll.cpp @@ -50,7 +50,7 @@ bool qax_ownQApp = false; HHOOK qax_hhook = 0; // in qaxserver.cpp -extern char qAxModuleFilename[MAX_PATH]; +extern wchar_t qAxModuleFilename[MAX_PATH]; extern bool qAxIsServer; extern ITypeLib *qAxTypeLibrary; extern unsigned long qAxLockCount(); @@ -120,7 +120,7 @@ STDAPI DllCanUnloadNow() EXTERN_C BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpvReserved) { - GetModuleFileNameA(hInstance, qAxModuleFilename, MAX_PATH-1); + GetModuleFileName(hInstance, qAxModuleFilename, MAX_PATH); qAxInstance = hInstance; qAxIsServer = true; diff --git a/src/activeqt/control/qaxservermain.cpp b/src/activeqt/control/qaxservermain.cpp index 8f20d97..d465746 100644 --- a/src/activeqt/control/qaxservermain.cpp +++ b/src/activeqt/control/qaxservermain.cpp @@ -66,7 +66,7 @@ extern bool qAxActivity; extern HANDLE qAxInstance; extern bool qAxIsServer; extern bool qAxOutProcServer; -extern char qAxModuleFilename[MAX_PATH]; +extern wchar_t qAxModuleFilename[MAX_PATH]; extern QString qAxInit(); extern void qAxCleanup(); extern HRESULT UpdateRegistry(BOOL bRegister); @@ -105,7 +105,7 @@ static DWORD WINAPI MonitorProc(void* pv) static bool StartMonitor() { dwThreadID = GetCurrentThreadId(); - hEventShutdown = CreateEventA(0, false, false, 0); + hEventShutdown = CreateEvent(0, false, false, 0); if (hEventShutdown == 0) return false; DWORD dwThreadID; @@ -203,17 +203,10 @@ EXTERN_C int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR, QT_USE_NAMESPACE qAxOutProcServer = true; - GetModuleFileNameA(0, qAxModuleFilename, MAX_PATH-1); + GetModuleFileName(0, qAxModuleFilename, MAX_PATH); qAxInstance = hInstance; - QByteArray cmdParam; - QT_WA({ - LPTSTR cmdline = GetCommandLineW(); - cmdParam = QString::fromUtf16((const ushort *)cmdline).toLocal8Bit(); - }, { - cmdParam = GetCommandLineA(); - }); - + QByteArray cmdParam = QString::fromWCharArray(GetCommandLine()).toLocal8Bit(); QList cmds = cmdParam.split(' '); QByteArray unprocessed; diff --git a/src/activeqt/shared/qaxtypes.cpp b/src/activeqt/shared/qaxtypes.cpp index 916fcca..49aa99c 100644 --- a/src/activeqt/shared/qaxtypes.cpp +++ b/src/activeqt/shared/qaxtypes.cpp @@ -37,11 +37,6 @@ ** ****************************************************************************/ -#ifndef UNICODE -#define UNICODE -#endif - - #include #include @@ -123,7 +118,7 @@ static QFont IFontToQFont(IFont *f) f->get_Strikethrough(&strike); f->get_Underline(&underline); f->get_Weight(&weight); - QFont font(QString::fromUtf16((const ushort *)name), size.Lo/9750, weight / 97, italic); + QFont font(QString::fromWCharArray(name), size.Lo/9750, weight / 97, italic); font.setBold(bold); font.setStrikeOut(strike); font.setUnderline(underline); @@ -925,10 +920,10 @@ QVariant VARIANTToQVariant(const VARIANT &arg, const QByteArray &typeName, uint QVariant var; switch(arg.vt) { case VT_BSTR: - var = QString::fromUtf16((const ushort *)arg.bstrVal); + var = QString::fromWCharArray(arg.bstrVal); break; case VT_BSTR|VT_BYREF: - var = QString::fromUtf16((const ushort *)*arg.pbstrVal); + var = QString::fromWCharArray(*arg.pbstrVal); break; case VT_BOOL: var = QVariant((bool)arg.boolVal); @@ -1245,7 +1240,7 @@ QVariant VARIANTToQVariant(const VARIANT &arg, const QByteArray &typeName, uint for (long i = lBound; i <= uBound; ++i) { BSTR bstr; SafeArrayGetElement(array, &i, &bstr); - strings << QString::fromUtf16((const ushort *)bstr); + strings << QString::fromWCharArray(bstr); SysFreeString(bstr); } -- cgit v0.12 From 8a7fb1881afe6b358a35cec71247d7e6681efe0a Mon Sep 17 00:00:00 2001 From: miniak Date: Wed, 1 Jul 2009 11:50:10 +0200 Subject: src/qt3support: Remove QT_WA and non-Unicode code paths, dropping Win9x and NT support Merge-request: 604 Reviewed-by: Marius Storm-Olsen --- src/corelib/global/qt_windows.h | 9 + src/qt3support/dialogs/q3filedialog.cpp | 206 ++----------- src/qt3support/dialogs/q3filedialog_win.cpp | 430 +++++++--------------------- src/qt3support/network/q3dns.cpp | 70 ++--- src/qt3support/other/q3dragobject.cpp | 7 +- src/qt3support/other/q3process_win.cpp | 152 ++++------ src/qt3support/widgets/q3datetimeedit.cpp | 48 +--- src/qt3support/widgets/q3titlebar.cpp | 33 +-- 8 files changed, 231 insertions(+), 724 deletions(-) diff --git a/src/corelib/global/qt_windows.h b/src/corelib/global/qt_windows.h index 27c06e5..4f2bcf6 100644 --- a/src/corelib/global/qt_windows.h +++ b/src/corelib/global/qt_windows.h @@ -99,6 +99,9 @@ #ifndef SPI_GETKEYBOARDCUES #define SPI_GETKEYBOARDCUES 0x100A #endif +#ifndef SPI_GETGRADIENTCAPTIONS +#define SPI_GETGRADIENTCAPTIONS 0x1008 +#endif #ifndef IDC_HAND #define IDC_HAND MAKEINTRESOURCE(32649) #endif @@ -111,6 +114,12 @@ #ifndef ETO_PDY #define ETO_PDY 0x2000 #endif +#ifndef COLOR_GRADIENTACTIVECAPTION +#define COLOR_GRADIENTACTIVECAPTION 27 +#endif +#ifndef COLOR_GRADIENTINACTIVECAPTION +#define COLOR_GRADIENTINACTIVECAPTION 28 +#endif // already defined when compiled with WINVER >= 0x0600 #ifndef SPI_GETFLATMENU diff --git a/src/qt3support/dialogs/q3filedialog.cpp b/src/qt3support/dialogs/q3filedialog.cpp index 031170e..a285fd8 100644 --- a/src/qt3support/dialogs/q3filedialog.cpp +++ b/src/qt3support/dialogs/q3filedialog.cpp @@ -507,45 +507,7 @@ static void updateLastSize(Q3FileDialog *that) lastHeight = that->height() - extHeight; } -// Don't remove the lines below! -// -// resolving the W methods manually is needed, because Windows 95 doesn't include -// these methods in Shell32.lib (not even stubs!), so you'd get an unresolved symbol -// when Qt calls getEsistingDirectory(), etc. #if defined(Q_WS_WIN) - -typedef UINT (WINAPI *PtrExtractIconEx)(LPCTSTR,int,HICON*,HICON*,UINT); -static PtrExtractIconEx ptrExtractIconEx = 0; - -static void resolveLibs() -{ -#ifndef Q_OS_WINCE - static bool triedResolve = false; - - if (!triedResolve) { -#ifndef QT_NO_THREAD - // protect initialization - QMutexLocker locker(QMutexPool::globalInstanceGet(&triedResolve)); - // check triedResolve again, since another thread may have already - // done the initialization - if (triedResolve) { - // another thread did initialize the security function pointers, - // so we shouldn't do it again. - return; - } -#endif - triedResolve = true; - if (qt_winUnicode()) { - QLibrary lib(QLatin1String("shell32")); - ptrExtractIconEx = (PtrExtractIconEx) lib.resolve("ExtractIconExW"); - } - } -#endif -} -#ifdef Q_OS_WINCE -#define PtrExtractIconEx ExtractIconEx -#endif - class QWindowsIconProvider : public Q3FileIconProvider { public: @@ -2566,11 +2528,7 @@ void Q3FileDialog::init() d->modeButtons->insert(d->previewInfo); d->previewContents = new QToolButton(this, "preview info view"); -#if defined(Q_WS_WIN) && !defined(Q_OS_WINCE) - if ((qWinVersion() & Qt::WV_NT_based) > Qt::WV_NT) -#else if (!qstrcmp(style()->className(), "QWindowsStyle")) -#endif { d->goBack->setAutoRaise(true); d->cdToParent->setAutoRaise(true); @@ -4878,33 +4836,20 @@ Q3FileIconProvider * Q3FileDialog::iconProvider() static QString getWindowsRegString(HKEY key, const QString &subKey) { QString s; - QT_WA({ - char buf[1024]; - DWORD bsz = sizeof(buf); - int r = RegQueryValueEx(key, (TCHAR*)subKey.ucs2(), 0, 0, (LPBYTE)buf, &bsz); - if (r == ERROR_SUCCESS) { - s = QString::fromUcs2((unsigned short *)buf); - } else if (r == ERROR_MORE_DATA) { - char *ptr = new char[bsz+1]; - r = RegQueryValueEx(key, (TCHAR*)subKey.ucs2(), 0, 0, (LPBYTE)ptr, &bsz); - if (r == ERROR_SUCCESS) - s = QLatin1String(ptr); - delete [] ptr; - } - } , { - char buf[512]; - DWORD bsz = sizeof(buf); - int r = RegQueryValueExA(key, subKey.local8Bit(), 0, 0, (LPBYTE)buf, &bsz); - if (r == ERROR_SUCCESS) { - s = QLatin1String(buf); - } else if (r == ERROR_MORE_DATA) { - char *ptr = new char[bsz+1]; - r = RegQueryValueExA(key, subKey.local8Bit(), 0, 0, (LPBYTE)ptr, &bsz); - if (r == ERROR_SUCCESS) - s = QLatin1String(ptr); - delete [] ptr; - } - }); + + wchar_t buf[1024]; + DWORD bsz = sizeof(buf) / sizeof(wchar_t); + int r = RegQueryValueEx(key, (wchar_t*)subKey.utf16(), 0, 0, (LPBYTE)buf, &bsz); + if (r == ERROR_SUCCESS) { + s = QString::fromWCharArray(buf); + } else if (r == ERROR_MORE_DATA) { + char *ptr = new char[bsz+1]; + r = RegQueryValueEx(key, (wchar_t*)subKey.utf16(), 0, 0, (LPBYTE)ptr, &bsz); + if (r == ERROR_SUCCESS) + s = QLatin1String(ptr); + delete [] ptr; + } + return s; } @@ -4925,22 +4870,13 @@ QWindowsIconProvider::QWindowsIconProvider(QObject *parent, const char *name) HKEY k; HICON si; - int r; QString s; UINT res = 0; // ---------- get default folder pixmap const wchar_t iconFolder[] = L"folder\\DefaultIcon"; // workaround for Borland - QT_WA({ - r = RegOpenKeyEx(HKEY_CLASSES_ROOT, - iconFolder, - 0, KEY_READ, &k); - } , { - r = RegOpenKeyExA(HKEY_CLASSES_ROOT, - "folder\\DefaultIcon", - 0, KEY_READ, &k); - }); - resolveLibs(); + int r = RegOpenKeyEx(HKEY_CLASSES_ROOT, iconFolder, 0, KEY_READ, &k); + if (r == ERROR_SUCCESS) { s = getWindowsRegString(k, QString()); RegCloseKey(k); @@ -4948,21 +4884,7 @@ QWindowsIconProvider::QWindowsIconProvider(QObject *parent, const char *name) QStringList lst = QStringList::split(QLatin1String(","), s); if (lst.count() >= 2) { // don't just assume that lst has two entries -#ifndef Q_OS_WINCE - QT_WA({ - res = ptrExtractIconEx((TCHAR*)lst[0].simplifyWhiteSpace().ucs2(), - lst[1].simplifyWhiteSpace().toInt(), - 0, &si, 1); - } , { - res = ExtractIconExA(lst[0].simplifyWhiteSpace().local8Bit(), - lst[1].simplifyWhiteSpace().toInt(), - 0, &si, 1); - }); -#else - res = (UINT)ExtractIconEx((TCHAR*)lst[0].simplifyWhiteSpace().ucs2(), - lst[1].simplifyWhiteSpace().toInt(), - 0, &si, 1); -#endif + res = ExtractIconEx((wchar_t*)lst[0].simplifyWhiteSpace().utf16(), lst[1].simplifyWhiteSpace().toInt(), 0, &si, 1); } if (res) { @@ -4978,18 +4900,7 @@ QWindowsIconProvider::QWindowsIconProvider(QObject *parent, const char *name) } //------------------------------- get default file pixmap -#ifndef Q_OS_WINCE - QT_WA({ - res = ptrExtractIconEx(L"shell32.dll", - 0, 0, &si, 1); - } , { - res = ExtractIconExA("shell32.dll", - 0, 0, &si, 1); - }); -#else - res = (UINT)ExtractIconEx(L"shell32.dll", - 0, 0, &si, 1); -#endif + res = ExtractIconEx(L"shell32.dll", 0, 0, &si, 1); if (res) { defaultFile = fromHICON(si); @@ -5002,16 +4913,9 @@ QWindowsIconProvider::QWindowsIconProvider(QObject *parent, const char *name) //------------------------------- get default exe pixmap #ifndef Q_OS_WINCE - QT_WA({ - res = ptrExtractIconEx(L"shell32.dll", - 2, 0, &si, 1); - } , { - res = ExtractIconExA("shell32.dll", - 2, 0, &si, 1); - }); + res = ExtractIconEx(L"shell32.dll", 2, 0, &si, 1); #else - res = (UINT)ExtractIconEx(L"ceshell.dll", - 10, 0, &si, 1); + res = ExtractIconEx(L"ceshell.dll", 10, 0, &si, 1); #endif if (res) { @@ -5050,14 +4954,7 @@ const QPixmap * QWindowsIconProvider::pixmap(const QFileInfo &fi) return &(*it); HKEY k, k2; - int r; - QT_WA({ - r = RegOpenKeyEx(HKEY_CLASSES_ROOT, (TCHAR*)ext.ucs2(), - 0, KEY_READ, &k); - } , { - r = RegOpenKeyExA(HKEY_CLASSES_ROOT, ext.local8Bit(), - 0, KEY_READ, &k); - }); + int r = RegOpenKeyEx(HKEY_CLASSES_ROOT, (wchar_t*)ext.utf16(), 0, KEY_READ, &k); QString s; if (r == ERROR_SUCCESS) { s = getWindowsRegString(k, QString()); @@ -5068,13 +4965,8 @@ const QPixmap * QWindowsIconProvider::pixmap(const QFileInfo &fi) } RegCloseKey(k); - QT_WA({ - r = RegOpenKeyEx(HKEY_CLASSES_ROOT, (TCHAR*)QString(s + QLatin1String("\\DefaultIcon")).ucs2(), - 0, KEY_READ, &k2); - } , { - r = RegOpenKeyExA(HKEY_CLASSES_ROOT, QString(s + QLatin1String("\\DefaultIcon")).local8Bit() , - 0, KEY_READ, &k2); - }); + r = RegOpenKeyEx(HKEY_CLASSES_ROOT, (wchar_t*)QString(s + QLatin1String("\\DefaultIcon")).utf16(), + 0, KEY_READ, &k2); if (r == ERROR_SUCCESS) { s = getWindowsRegString(k2, QString()); } else { @@ -5104,19 +4996,7 @@ const QPixmap * QWindowsIconProvider::pixmap(const QFileInfo &fi) if (filepath[0] == QLatin1Char('"') && filepath[(int)filepath.length()-1] == QLatin1Char('"')) filepath = filepath.mid(1, filepath.length()-2); - resolveLibs(); -#ifndef Q_OS_WINCE - QT_WA({ - res = ptrExtractIconEx((TCHAR*)filepath.ucs2(), lst[1].stripWhiteSpace().toInt(), - 0, &si, 1); - } , { - res = ExtractIconExA(filepath.local8Bit(), lst[1].stripWhiteSpace().toInt(), - 0, &si, 1); - }); -#else - res = (UINT)ExtractIconEx((TCHAR*)filepath.ucs2(), lst[1].stripWhiteSpace().toInt(), - 0, &si, 1); -#endif + res = ExtractIconEx((wchar_t*)filepath.utf16(), lst[1].stripWhiteSpace().toInt(), 0, &si, 1); } } if (res) { @@ -5133,32 +5013,9 @@ const QPixmap * QWindowsIconProvider::pixmap(const QFileInfo &fi) HICON si; UINT res = 0; if (!fi.absFilePath().isEmpty()) { -#ifndef Q_OS_WINCE - QT_WA({ - res = ptrExtractIconEx((TCHAR*)fi.absFilePath().ucs2(), -1, - 0, 0, 1); - } , { - res = ExtractIconExA(fi.absFilePath().local8Bit(), -1, - 0, 0, 1); - }); - - if (res) { - QT_WA({ - res = ptrExtractIconEx((TCHAR*)fi.absFilePath().ucs2(), res - 1, - 0, &si, 1); - } , { - res = ExtractIconExA(fi.absFilePath().local8Bit(), res - 1, - 0, &si, 1); - }); - } -#else - res = (UINT)ExtractIconEx((TCHAR*)fi.absFilePath().ucs2(), -1, - 0, 0, 1); - if (res) - res = (UINT)ExtractIconEx((TCHAR*)fi.absFilePath().ucs2(), res - 1, - 0, &si, 1); -#endif - + res = ExtractIconEx((wchar_t*)fi.absFilePath().utf16(), -1, 0, 0, 1); + if (res) + res = ExtractIconEx((wchar_t*)fi.absFilePath().utf16(), res - 1, 0, &si, 1); } if (res) { @@ -5760,13 +5617,8 @@ void Q3FileDialog::insertEntry(const Q3ValueList &lst, Q3NetworkOperat if (!file.endsWith(QLatin1Char('/'))) file.append(QLatin1Char('/')); file += inf.name(); - QT_WA({ - if (GetFileAttributesW((TCHAR*)file.ucs2()) & FILE_ATTRIBUTE_HIDDEN) - continue; - } , { - if (GetFileAttributesA(file.local8Bit()) & FILE_ATTRIBUTE_HIDDEN) - continue; - }); + if (GetFileAttributes((wchar_t*)file.utf16()) & FILE_ATTRIBUTE_HIDDEN) + continue; } else { if (inf.name() != QLatin1String("..") && inf.name()[0] == QLatin1Char('.')) continue; diff --git a/src/qt3support/dialogs/q3filedialog_win.cpp b/src/qt3support/dialogs/q3filedialog_win.cpp index ed86fa2..487097a 100644 --- a/src/qt3support/dialogs/q3filedialog_win.cpp +++ b/src/qt3support/dialogs/q3filedialog_win.cpp @@ -64,49 +64,6 @@ QT_BEGIN_NAMESPACE -// Don't remove the lines below! -// -// resolving the W methods manually is needed, because Windows 95 doesn't include -// these methods in Shell32.lib (not even stubs!), so you'd get an unresolved symbol -// when Qt calls getEsistingDirectory(), etc. -typedef LPITEMIDLIST (WINAPI *PtrSHBrowseForFolder)(BROWSEINFO*); -static PtrSHBrowseForFolder ptrSHBrowseForFolder = 0; -typedef BOOL (WINAPI *PtrSHGetPathFromIDList)(LPITEMIDLIST,LPWSTR); -static PtrSHGetPathFromIDList ptrSHGetPathFromIDList = 0; - -static void resolveLibs() -{ -#ifndef Q_OS_WINCE - static bool triedResolve = false; - - if (!triedResolve) { -#ifndef QT_NO_THREAD - // protect initialization - QMutexLocker locker(QMutexPool::globalInstanceGet(&triedResolve)); - // check triedResolve again, since another thread may have already - // done the initialization - if (triedResolve) { - // another thread did initialize the security function pointers, - // so we shouldn't do it again. - return; - } -#endif - - triedResolve = true; - if (qt_winUnicode()) { - QLibrary lib(QLatin1String("shell32")); - ptrSHBrowseForFolder = (PtrSHBrowseForFolder) lib.resolve("SHBrowseForFolderW"); - ptrSHGetPathFromIDList = (PtrSHGetPathFromIDList) lib.resolve("SHGetPathFromIDListW"); - } - } -#endif -} -#ifdef Q_OS_WINCE -#define PtrSHBrowseForFolder SHBrowseForFolder ; -#define PtrSHGetPathFromIDList SHGetPathFromIDList; -#endif - - extern const char qt3_file_dialog_filter_reg_exp[]; // defined in qfiledialog.cpp const int maxNameLen = 1023; @@ -168,80 +125,8 @@ static QString selFilter(const QString& filter, DWORD idx) return filterLst[(int)idx - 1]; } -#ifndef Q_OS_WINCE -// Static vars for OFNA funcs: -static QByteArray aInitDir; -static QByteArray aInitSel; -static QByteArray aTitle; -static QByteArray aFilter; -// Use ANSI strings and API - -// If you change this, then make sure you change makeOFN (below) too -static -OPENFILENAMEA* makeOFNA(QWidget* parent, - const QString& initialSelection, - const QString& initialDirectory, - const QString& title, - const QString& filters, - Q3FileDialog::Mode mode) -{ - if (parent) - parent = parent->window(); - else - parent = qApp->activeWindow(); - - aTitle = title.local8Bit(); - aInitDir = QDir::toNativeSeparators(initialDirectory).local8Bit(); - if (initialSelection.isEmpty()) - aInitSel = ""; - else - aInitSel = QDir::toNativeSeparators(initialSelection).local8Bit(); - int maxLen = mode == Q3FileDialog::ExistingFiles ? maxMultiLen : maxNameLen; - aInitSel.resize(maxLen + 1); // make room for return value - aFilter = filters.local8Bit(); - - OPENFILENAMEA* ofn = new OPENFILENAMEA; - memset(ofn, 0, sizeof(OPENFILENAMEA)); - -#if defined(Q_CC_BOR) && (WINVER >= 0x0500) && (_WIN32_WINNT >= 0x0500) - // according to the MSDN, this should also be necessary for MSVC, but - // OPENFILENAME_SIZE_VERSION_400A is in not Microsoft header, as it seems - if (QApplication::winVersion()==Qt::WV_NT || QApplication::winVersion()&Qt::WV_DOS_based) { - ofn->lStructSize= OPENFILENAME_SIZE_VERSION_400A; - } else { - ofn->lStructSize= sizeof(OPENFILENAMEA); - } -#else - ofn->lStructSize = sizeof(OPENFILENAMEA); -#endif - ofn->hwndOwner = parent ? parent->winId() : 0; - ofn->lpstrFilter = aFilter; - ofn->lpstrFile = aInitSel.data(); - ofn->nMaxFile = maxLen; - ofn->lpstrInitialDir = aInitDir.data(); - ofn->lpstrTitle = aTitle.data(); - ofn->Flags = (OFN_NOCHANGEDIR | OFN_HIDEREADONLY); - - if (mode == Q3FileDialog::ExistingFile || - mode == Q3FileDialog::ExistingFiles) - ofn->Flags |= (OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST); - if (mode == Q3FileDialog::ExistingFiles) - ofn->Flags |= (OFN_ALLOWMULTISELECT | OFN_EXPLORER); - - return ofn; -} - -static void cleanUpOFNA(OPENFILENAMEA** ofn) -{ - delete *ofn; - *ofn = 0; -} -#endif - static QString tFilters, tTitle, tInitDir; -#ifdef UNICODE -// If you change this, then make sure you change makeOFNA (above) too static OPENFILENAME* makeOFN(QWidget* parent, const QString& initialSelection, @@ -261,33 +146,23 @@ OPENFILENAME* makeOFN(QWidget* parent, QString initSel = QDir::toNativeSeparators(initialSelection); int maxLen = mode == Q3FileDialog::ExistingFiles ? maxMultiLen : maxNameLen; - TCHAR *tInitSel = new TCHAR[maxLen+1]; + wchar_t *tInitSel = new wchar_t[maxLen+1]; if (initSel.length() > 0 && initSel.length() <= maxLen) - memcpy(tInitSel, initSel.ucs2(), (initSel.length()+1)*sizeof(QChar)); + memcpy(tInitSel, initSel.utf16(), (initSel.length() + 1) * sizeof(wchar_t)); else tInitSel[0] = 0; OPENFILENAME* ofn = new OPENFILENAME; memset(ofn, 0, sizeof(OPENFILENAME)); -#if defined(Q_CC_BOR) && (WINVER >= 0x0500) && (_WIN32_WINNT >= 0x0500) - // according to the MSDN, this should also be necessary for MSVC, but - // OPENFILENAME_SIZE_VERSION_400 is in not Microsoft header, as it seems - if (QApplication::winVersion()==Qt::WV_NT || QApplication::winVersion()&Qt::WV_DOS_based) { - ofn->lStructSize= OPENFILENAME_SIZE_VERSION_400; - } else { - ofn->lStructSize = sizeof(OPENFILENAME); - } -#else - ofn->lStructSize = sizeof(OPENFILENAME); -#endif - ofn->hwndOwner = parent ? parent->winId() : 0; - ofn->lpstrFilter = (TCHAR *)tFilters.ucs2(); - ofn->lpstrFile = tInitSel; + ofn->lStructSize = sizeof(OPENFILENAME); + ofn->hwndOwner = parent ? parent->winId() : 0; + ofn->lpstrFilter = (wchar_t*)tFilters.utf16(); + ofn->lpstrFile = tInitSel; ofn->nMaxFile = maxLen; - ofn->lpstrInitialDir = (TCHAR *)tInitDir.ucs2(); - ofn->lpstrTitle = (TCHAR *)tTitle.ucs2(); - ofn->Flags = (OFN_NOCHANGEDIR | OFN_HIDEREADONLY); + ofn->lpstrInitialDir = (wchar_t*)tInitDir.utf16(); + ofn->lpstrTitle = (wchar_t*)tTitle.utf16(); + ofn->Flags = (OFN_NOCHANGEDIR | OFN_HIDEREADONLY); if (mode == Q3FileDialog::ExistingFile || mode == Q3FileDialog::ExistingFiles) @@ -298,7 +173,6 @@ OPENFILENAME* makeOFN(QWidget* parent, return ofn; } - static void cleanUpOFN(OPENFILENAME** ofn) { delete (*ofn)->lpstrFile; @@ -306,8 +180,6 @@ static void cleanUpOFN(OPENFILENAME** ofn) *ofn = 0; } -#endif // UNICODE - QString Q3FileDialog::winGetOpenFileName(const QString &initialSelection, const QString &filter, QString* initialDirectory, @@ -349,31 +221,18 @@ QString Q3FileDialog::winGetOpenFileName(const QString &initialSelection, QApplication::sendEvent(parent, &e); QApplicationPrivate::enterModal(parent); } - QT_WA({ - // Use Unicode strings and API - OPENFILENAME* ofn = makeOFN(parent, isel, - *initialDirectory, title, - winFilter(filter), ExistingFile); - if (idx) - ofn->nFilterIndex = idx + 1; - if (GetOpenFileName(ofn)) { - result = QString::fromUcs2((ushort*)ofn->lpstrFile); - selFilIdx = ofn->nFilterIndex; - } - cleanUpOFN(&ofn); - } , { - // Use ANSI strings and API - OPENFILENAMEA* ofn = makeOFNA(parent, isel, - *initialDirectory, title, - winFilter(filter), ExistingFile); - if (idx) - ofn->nFilterIndex = idx + 1; - if (GetOpenFileNameA(ofn)) { - result = QString::fromLocal8Bit(ofn->lpstrFile); - selFilIdx = ofn->nFilterIndex; - } - cleanUpOFNA(&ofn); - }); + + OPENFILENAME* ofn = makeOFN(parent, isel, + *initialDirectory, title, + winFilter(filter), ExistingFile); + if (idx) + ofn->nFilterIndex = idx + 1; + if (GetOpenFileName(ofn)) { + result = QString::fromWCharArray(ofn->lpstrFile); + selFilIdx = ofn->nFilterIndex; + } + cleanUpOFN(&ofn); + if (parent) { QApplicationPrivate::leaveModal(parent); QEvent e(QEvent::WindowUnblocked); @@ -433,31 +292,18 @@ QString Q3FileDialog::winGetSaveFileName(const QString &initialSelection, QApplication::sendEvent(parent, &e); QApplicationPrivate::enterModal(parent); } - QT_WA({ - // Use Unicode strings and API - OPENFILENAME* ofn = makeOFN(parent, isel, - *initialDirectory, title, - winFilter(filter), AnyFile); - if (idx) - ofn->nFilterIndex = idx + 1; - if (GetSaveFileName(ofn)) { - result = QString::fromUcs2((ushort*)ofn->lpstrFile); - selFilIdx = ofn->nFilterIndex; - } - cleanUpOFN(&ofn); - } , { - // Use ANSI strings and API - OPENFILENAMEA* ofn = makeOFNA(parent, isel, - *initialDirectory, title, - winFilter(filter), AnyFile); - if (idx) - ofn->nFilterIndex = idx + 1; - if (GetSaveFileNameA(ofn)) { - result = QString::fromLocal8Bit(ofn->lpstrFile); - selFilIdx = ofn->nFilterIndex; - } - cleanUpOFNA(&ofn); - }); + + OPENFILENAME* ofn = makeOFN(parent, isel, + *initialDirectory, title, + winFilter(filter), AnyFile); + if (idx) + ofn->nFilterIndex = idx + 1; + if (GetSaveFileName(ofn)) { + result = QString::fromWCharArray(ofn->lpstrFile); + selFilIdx = ofn->nFilterIndex; + } + cleanUpOFN(&ofn); + if (parent) { QApplicationPrivate::leaveModal(parent); QEvent e(QEvent::WindowUnblocked); @@ -519,69 +365,38 @@ QStringList Q3FileDialog::winGetOpenFileNames(const QString &filter, QApplication::sendEvent(parent, &e); QApplicationPrivate::enterModal(parent); } - QT_WA({ - OPENFILENAME* ofn = makeOFN(parent, isel, - *initialDirectory, title, - winFilter(filter), ExistingFiles); - if (idx) - ofn->nFilterIndex = idx + 1; - if (GetOpenFileName(ofn)) { - QString fileOrDir = QString::fromUcs2((ushort*)ofn->lpstrFile); - selFilIdx = ofn->nFilterIndex; - int offset = fileOrDir.length() + 1; - if (ofn->lpstrFile[offset] == 0) { - // Only one file selected; has full path - fi.setFile(fileOrDir); - QString res = fi.absFilePath(); - if (!res.isEmpty()) - result.append(res); - } - else { - // Several files selected; first string is path - dir.setPath(fileOrDir); - QString f; - while(!(f = QString::fromUcs2((ushort*)ofn->lpstrFile+offset)).isEmpty()) { - fi.setFile(dir, f); - QString res = fi.absFilePath(); - if (!res.isEmpty()) - result.append(res); - offset += f.length() + 1; - } - } + + OPENFILENAME* ofn = makeOFN(parent, isel, + *initialDirectory, title, + winFilter(filter), ExistingFiles); + if (idx) + ofn->nFilterIndex = idx + 1; + if (GetOpenFileName(ofn)) { + QString fileOrDir = QString::fromWCharArray(ofn->lpstrFile); + selFilIdx = ofn->nFilterIndex; + int offset = fileOrDir.length() + 1; + if (ofn->lpstrFile[offset] == 0) { + // Only one file selected; has full path + fi.setFile(fileOrDir); + QString res = fi.absFilePath(); + if (!res.isEmpty()) + result.append(res); } - cleanUpOFN(&ofn); - } , { - OPENFILENAMEA* ofn = makeOFNA(parent, isel, - *initialDirectory, title, - winFilter(filter), ExistingFiles); - if (idx) - ofn->nFilterIndex = idx + 1; - if (GetOpenFileNameA(ofn)) { - QByteArray fileOrDir(ofn->lpstrFile); - selFilIdx = ofn->nFilterIndex; - int offset = fileOrDir.length() + 1; - if (ofn->lpstrFile[offset] == '\0') { - // Only one file selected; has full path - fi.setFile(QString::fromLocal8Bit(fileOrDir)); + else { + // Several files selected; first string is path + dir.setPath(fileOrDir); + QString f; + while (!(f = QString::fromWCharArray(ofn->lpstrFile + offset)).isEmpty()) { + fi.setFile(dir, f); QString res = fi.absFilePath(); if (!res.isEmpty()) result.append(res); + offset += f.length() + 1; } - else { - // Several files selected; first string is path - dir.setPath(QString::fromLocal8Bit(fileOrDir)); - QByteArray f; - while(!(f = QByteArray(ofn->lpstrFile + offset)).isEmpty()) { - fi.setFile(dir, QString::fromLocal8Bit(f)); - QString res = fi.absFilePath(); - if (!res.isEmpty()) - result.append(res); - offset += f.length() + 1; - } - } - cleanUpOFNA(&ofn); } - }); + } + cleanUpOFN(&ofn); + if (parent) { QApplicationPrivate::leaveModal(parent); QEvent e(QEvent::WindowUnblocked); @@ -607,34 +422,17 @@ static int __stdcall winGetExistDirCallbackProc(HWND hwnd, if (uMsg == BFFM_INITIALIZED && lpData != 0) { QString *initDir = (QString *)(lpData); if (!initDir->isEmpty()) { - // ### Lars asks: is this correct for the A version???? - QT_WA({ - SendMessage(hwnd, BFFM_SETSELECTION, TRUE, Q_ULONG(initDir->ucs2())); - } , { - SendMessageA(hwnd, BFFM_SETSELECTION, TRUE, Q_ULONG(initDir->ucs2())); - }); + SendMessage(hwnd, BFFM_SETSELECTION, TRUE, Q_ULONG(initDir->utf16())); } } else if (uMsg == BFFM_SELCHANGED) { - QT_WA({ - resolveLibs(); - TCHAR path[MAX_PATH]; - ptrSHGetPathFromIDList(LPITEMIDLIST(lParam), path); - QString tmpStr = QString::fromUcs2((ushort*)path); - if (!tmpStr.isEmpty()) - SendMessage(hwnd, BFFM_ENABLEOK, 1, 1); - else - SendMessage(hwnd, BFFM_ENABLEOK, 0, 0); - SendMessage(hwnd, BFFM_SETSTATUSTEXT, 1, Q_ULONG(path)); - } , { - char path[MAX_PATH]; - SHGetPathFromIDListA(LPITEMIDLIST(lParam), path); - QString tmpStr = QString::fromLocal8Bit(path); - if (!tmpStr.isEmpty()) - SendMessageA(hwnd, BFFM_ENABLEOK, 1, 1); - else - SendMessageA(hwnd, BFFM_ENABLEOK, 0, 0); - SendMessageA(hwnd, BFFM_SETSTATUSTEXT, 1, Q_ULONG(path)); - }); + wchar_t path[MAX_PATH]; + SHGetPathFromIDList(LPITEMIDLIST(lParam), path); + QString tmpStr = QString::fromWCharArray(path); + if (!tmpStr.isEmpty()) + SendMessage(hwnd, BFFM_ENABLEOK, 1, 1); + else + SendMessage(hwnd, BFFM_ENABLEOK, 0, 0); + SendMessage(hwnd, BFFM_SETSTATUSTEXT, 1, Q_ULONG(path)); } #endif return 0; @@ -666,76 +464,42 @@ QString Q3FileDialog::winGetExistingDirectory(const QString& initialDirectory, QApplication::sendEvent(parent, &e); QApplicationPrivate::enterModal(parent); } - QT_WA({ - resolveLibs(); - QString initDir = QDir::toNativeSeparators(initialDirectory); - TCHAR path[MAX_PATH]; - TCHAR initPath[MAX_PATH]; - initPath[0] = 0; - path[0] = 0; - tTitle = title; - BROWSEINFO bi; - bi.hwndOwner = (parent ? parent->winId() : 0); - bi.pidlRoot = NULL; - bi.lpszTitle = (TCHAR*)tTitle.ucs2(); - bi.pszDisplayName = initPath; - bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT | BIF_NEWDIALOGSTYLE; - bi.lpfn = winGetExistDirCallbackProc; - bi.lParam = Q_ULONG(&initDir); - LPITEMIDLIST pItemIDList = ptrSHBrowseForFolder(&bi); - if (pItemIDList) { - ptrSHGetPathFromIDList(pItemIDList, path); - IMalloc *pMalloc; - if (SHGetMalloc(&pMalloc) != NOERROR) - result.clear(); - else { - pMalloc->Free(pItemIDList); - pMalloc->Release(); - result = QString::fromUcs2((ushort*)path); - } - } else - result.clear(); - tTitle.clear(); - } , { - QString initDir = QDir::toNativeSeparators(initialDirectory); - char path[MAX_PATH]; - char initPath[MAX_PATH]; - QByteArray ctitle = title.toLocal8Bit(); - initPath[0]=0; - path[0]=0; - BROWSEINFOA bi; - bi.hwndOwner = (parent ? parent->winId() : 0); - bi.pidlRoot = NULL; - bi.lpszTitle = ctitle; - bi.pszDisplayName = initPath; - bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT | BIF_NEWDIALOGSTYLE; - bi.lpfn = winGetExistDirCallbackProc; - bi.lParam = Q_ULONG(&initDir); - LPITEMIDLIST pItemIDList = SHBrowseForFolderA(&bi); - if (pItemIDList) { - SHGetPathFromIDListA(pItemIDList, path); - IMalloc *pMalloc; - if (SHGetMalloc(&pMalloc) != NOERROR) - result.clear(); - else { - pMalloc->Free(pItemIDList); - pMalloc->Release(); - result = QString::fromLocal8Bit(path); - } - } else + + QString initDir = QDir::toNativeSeparators(initialDirectory); + wchar_t path[MAX_PATH]; + wchar_t initPath[MAX_PATH]; + initPath[0] = 0; + path[0] = 0; + tTitle = title; + BROWSEINFO bi; + bi.hwndOwner = (parent ? parent->winId() : 0); + bi.pidlRoot = NULL; + bi.lpszTitle = (wchar_t*)tTitle.utf16(); + bi.pszDisplayName = initPath; + bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT | BIF_NEWDIALOGSTYLE; + bi.lpfn = winGetExistDirCallbackProc; + bi.lParam = Q_ULONG(&initDir); + LPITEMIDLIST pItemIDList = SHBrowseForFolder(&bi); + if (pItemIDList) { + SHGetPathFromIDList(pItemIDList, path); + IMalloc *pMalloc; + if (SHGetMalloc(&pMalloc) != NOERROR) result.clear(); - }); + else { + pMalloc->Free(pItemIDList); + pMalloc->Release(); + result = QString::fromWCharArray(path); + } + } else + result.clear(); + tTitle.clear(); + if (parent) { QApplicationPrivate::leaveModal(parent); QEvent e(QEvent::WindowUnblocked); QApplication::sendEvent(parent, &e); } - // Due to a bug on Windows Me, we need to reset the current - // directory - if ((qWinVersion() == Qt::WV_98 || qWinVersion() == Qt::WV_Me) && QDir::currentDirPath() != currentDir) - QDir::setCurrent(currentDir); - if (!result.isEmpty()) result.replace(QLatin1Char('\\'), QLatin1Char('/')); return result; diff --git a/src/qt3support/network/q3dns.cpp b/src/qt3support/network/q3dns.cpp index b80b76b..6d514c1 100644 --- a/src/qt3support/network/q3dns.cpp +++ b/src/qt3support/network/q3dns.cpp @@ -2242,53 +2242,31 @@ typedef struct { typedef DWORD (WINAPI *GNP)( PFIXED_INFO, PULONG ); // ### FIXME: this code is duplicated in qfiledialog.cpp -static QString getWindowsRegString( HKEY key, const QString &subKey ) +static QString getWindowsRegString(HKEY key, const QString &subKey) { QString s; - QT_WA( { - char buf[1024]; - DWORD bsz = sizeof(buf); - int r = RegQueryValueEx( key, (TCHAR*)subKey.ucs2(), 0, 0, (LPBYTE)buf, &bsz ); - if ( r == ERROR_SUCCESS ) { - s = QString::fromUcs2( (unsigned short *)buf ); - } else if ( r == ERROR_MORE_DATA ) { - char *ptr = new char[bsz+1]; - r = RegQueryValueEx( key, (TCHAR*)subKey.ucs2(), 0, 0, (LPBYTE)ptr, &bsz ); - if ( r == ERROR_SUCCESS ) - s = QLatin1String(ptr); - delete [] ptr; - } - } , { - char buf[512]; - DWORD bsz = sizeof(buf); - int r = RegQueryValueExA( key, subKey.local8Bit(), 0, 0, (LPBYTE)buf, &bsz ); - if ( r == ERROR_SUCCESS ) { - s = QLatin1String(buf); - } else if ( r == ERROR_MORE_DATA ) { - char *ptr = new char[bsz+1]; - r = RegQueryValueExA( key, subKey.local8Bit(), 0, 0, (LPBYTE)ptr, &bsz ); - if ( r == ERROR_SUCCESS ) - s = QLatin1String(ptr); - delete [] ptr; - } - } ); + + wchar_t buf[1024]; + DWORD bsz = sizeof(buf) / sizeof(wchar_t); + int r = RegQueryValueEx(key, (wchar_t*)subKey.utf16(), 0, 0, (LPBYTE)buf, &bsz); + if (r == ERROR_SUCCESS) { + s = QString::fromWCharArray(buf); + } else if (r == ERROR_MORE_DATA) { + char *ptr = new char[bsz+1]; + r = RegQueryValueEx(key, (wchar_t*)subKey.utf16(), 0, 0, (LPBYTE)ptr, &bsz); + if (r == ERROR_SUCCESS) + s = QLatin1String(ptr); + delete [] ptr; + } + return s; } static bool getDnsParamsFromRegistry( const QString &path, - QString *domainName, QString *nameServer, QString *searchList ) + QString *domainName, QString *nameServer, QString *searchList ) { HKEY k; - int r; - QT_WA( { - r = RegOpenKeyEx( HKEY_LOCAL_MACHINE, - (TCHAR*)path.ucs2(), - 0, KEY_READ, &k ); - } , { - r = RegOpenKeyExA( HKEY_LOCAL_MACHINE, - path.latin1(), - 0, KEY_READ, &k ); - } ); + int r = RegOpenKeyEx( HKEY_LOCAL_MACHINE, (wchar_t*)path.utf16(), 0, KEY_READ, &k ); if ( r == ERROR_SUCCESS ) { *domainName = getWindowsRegString( k, QLatin1String("DhcpDomain") ); @@ -2321,14 +2299,10 @@ void Q3Dns::doResInit() bool gotNetworkParams = false; // try the API call GetNetworkParams() first and use registry lookup only // as a fallback -#ifdef Q_OS_WINCE - HINSTANCE hinstLib = LoadLibraryW( L"iphlpapi" ); -#else - HINSTANCE hinstLib = LoadLibraryA( "iphlpapi" ); -#endif + HINSTANCE hinstLib = LoadLibrary( L"iphlpapi" ); if ( hinstLib != 0 ) { #ifdef Q_OS_WINCE - GNP getNetworkParams = (GNP) GetProcAddressW( hinstLib, L"GetNetworkParams" ); + GNP getNetworkParams = (GNP) GetProcAddress( hinstLib, L"GetNetworkParams" ); #else GNP getNetworkParams = (GNP) GetProcAddress( hinstLib, "GetNetworkParams" ); #endif @@ -2362,13 +2336,7 @@ void Q3Dns::doResInit() if ( getDnsParamsFromRegistry( QLatin1String("System\\CurrentControlSet\\Services\\Tcpip\\Parameters"), &domainName, &nameServer, &searchList )) { - // for NT separator = ' '; - } else if ( getDnsParamsFromRegistry( - QLatin1String("System\\CurrentControlSet\\Services\\VxD\\MSTCP"), - &domainName, &nameServer, &searchList )) { - // for Windows 98 - separator = ','; } else { // Could not access the TCP/IP parameters domainName = QLatin1String(""); diff --git a/src/qt3support/other/q3dragobject.cpp b/src/qt3support/other/q3dragobject.cpp index 0c17e0c..93a6079 100644 --- a/src/qt3support/other/q3dragobject.cpp +++ b/src/qt3support/other/q3dragobject.cpp @@ -191,8 +191,7 @@ Q3DragObject::~Q3DragObject() Set the pixmap, \a pm, to display while dragging the object. The platform-specific implementation will use this where it can - so provide a small masked pixmap, and do not assume that the user - will actually see it. For example, cursors on Windows 95 are of - limited size. + will actually see it. The \a hotspot is the point on (or off) the pixmap that should be under the cursor as it is dragged. It is relative to the top-left @@ -553,10 +552,6 @@ QTextCodec* qt_findcharset(const QByteArray& mimetype) i = cs.indexOf(';'); if (i >= 0) cs = cs.left(i); - // win98 often has charset=utf16, and we need to get the correct codec for - // it to be able to get Unicode text drops. - if (cs == "utf16") - cs = "ISO-10646-UCS-2"; // May return 0 if unknown charset return QTextCodec::codecForName(cs); } diff --git a/src/qt3support/other/q3process_win.cpp b/src/qt3support/other/q3process_win.cpp index 352e497..0952663 100644 --- a/src/qt3support/other/q3process_win.cpp +++ b/src/qt3support/other/q3process_win.cpp @@ -308,108 +308,60 @@ bool Q3Process::start( QStringList *env ) // CreateProcess() bool success; d->newPid(); -#ifdef UNICODE - if (!(QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based)) { - STARTUPINFOW startupInfo = { - sizeof( STARTUPINFO ), 0, 0, 0, - (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, - 0, 0, 0, - STARTF_USESTDHANDLES, - 0, 0, 0, - d->pipeStdin[0], d->pipeStdout[1], d->pipeStderr[1] - }; - TCHAR *applicationName; - if ( appName.isNull() ) - applicationName = 0; - else - applicationName = _wcsdup( (TCHAR*)appName.ucs2() ); - TCHAR *commandLine = _wcsdup( (TCHAR*)args.ucs2() ); - QByteArray envlist; - if ( env != 0 ) { - int pos = 0; - // add PATH if necessary (for DLL loading) - QByteArray path = qgetenv( "PATH" ); - if ( env->grep( QRegExp(QLatin1String("^PATH="),FALSE) ).empty() && !path.isNull() ) { - QString tmp = QString::fromLatin1("PATH=%1").arg(QLatin1String(path.constData())); - uint tmpSize = sizeof(TCHAR) * (tmp.length()+1); - envlist.resize( envlist.size() + tmpSize ); - memcpy( envlist.data()+pos, tmp.ucs2(), tmpSize ); - pos += tmpSize; - } - // add the user environment - for ( QStringList::Iterator it = env->begin(); it != env->end(); it++ ) { - QString tmp = *it; - uint tmpSize = sizeof(TCHAR) * (tmp.length()+1); - envlist.resize( envlist.size() + tmpSize ); - memcpy( envlist.data()+pos, tmp.ucs2(), tmpSize ); - pos += tmpSize; - } - // add the 2 terminating 0 (actually 4, just to be on the safe side) - envlist.resize( envlist.size()+4 ); - envlist[pos++] = 0; - envlist[pos++] = 0; - envlist[pos++] = 0; - envlist[pos++] = 0; - } - success = CreateProcessW( applicationName, commandLine, - 0, 0, TRUE, ( comms==0 ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW ) + + STARTUPINFOW startupInfo = { + sizeof( STARTUPINFO ), 0, 0, 0, + (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, + 0, 0, 0, + STARTF_USESTDHANDLES, + 0, 0, 0, + d->pipeStdin[0], d->pipeStdout[1], d->pipeStderr[1] + }; + wchar_t *applicationName; + if ( appName.isNull() ) + applicationName = 0; + else + applicationName = _wcsdup( (wchar_t*)appName.utf16() ); + wchar_t *commandLine = _wcsdup( (wchar_t*)args.utf16() ); + QByteArray envlist; + if ( env != 0 ) { + int pos = 0; + // add PATH if necessary (for DLL loading) + QByteArray path = qgetenv( "PATH" ); + if ( env->grep( QRegExp(QLatin1String("^PATH="),FALSE) ).empty() && !path.isNull() ) { + QString tmp = QString::fromLatin1("PATH=%1").arg(QLatin1String(path.constData())); + uint tmpSize = sizeof(wchar_t) * (tmp.length() + 1); + envlist.resize( envlist.size() + tmpSize ); + memcpy( envlist.data() + pos, tmp.utf16(), tmpSize ); + pos += tmpSize; + } + // add the user environment + for ( QStringList::Iterator it = env->begin(); it != env->end(); it++ ) { + QString tmp = *it; + uint tmpSize = sizeof(wchar_t) * (tmp.length() + 1); + envlist.resize( envlist.size() + tmpSize ); + memcpy( envlist.data() + pos, tmp.utf16(), tmpSize ); + pos += tmpSize; + } + // add the 2 terminating 0 (actually 4, just to be on the safe side) + envlist.resize( envlist.size()+4 ); + envlist[pos++] = 0; + envlist[pos++] = 0; + envlist[pos++] = 0; + envlist[pos++] = 0; + } + success = CreateProcess( applicationName, commandLine, + 0, 0, TRUE, ( comms == 0 ? CREATE_NEW_CONSOLE : CREATE_NO_WINDOW ) #ifndef Q_OS_WINCE - | CREATE_UNICODE_ENVIRONMENT + | CREATE_UNICODE_ENVIRONMENT #endif - , env==0 ? 0 : envlist.data(), - (TCHAR*)QDir::toNativeSeparators(workingDir.absPath()).ucs2(), - &startupInfo, d->pid ); - free( applicationName ); - free( commandLine ); - } else -#endif // UNICODE - { -#ifndef Q_OS_WINCE - STARTUPINFOA startupInfo = { sizeof( STARTUPINFOA ), 0, 0, 0, - (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, - 0, 0, 0, - STARTF_USESTDHANDLES, - 0, 0, 0, - d->pipeStdin[0], d->pipeStdout[1], d->pipeStderr[1] - }; - QByteArray envlist; - if ( env != 0 ) { - int pos = 0; - // add PATH if necessary (for DLL loading) - QByteArray path = qgetenv( "PATH" ); - if ( env->grep( QRegExp(QLatin1String("^PATH="),FALSE) ).empty() && !path.isNull() ) { - Q3CString tmp = QString::fromLatin1("PATH=%1").arg(QString::fromLatin1(path.constData())).local8Bit(); - uint tmpSize = tmp.length() + 1; - envlist.resize( envlist.size() + tmpSize ); - memcpy( envlist.data()+pos, tmp.data(), tmpSize ); - pos += tmpSize; - } - // add the user environment - for ( QStringList::Iterator it = env->begin(); it != env->end(); it++ ) { - Q3CString tmp = (*it).local8Bit(); - uint tmpSize = tmp.length() + 1; - envlist.resize( envlist.size() + tmpSize ); - memcpy( envlist.data()+pos, tmp.data(), tmpSize ); - pos += tmpSize; - } - // add the terminating 0 (actually 2, just to be on the safe side) - envlist.resize( envlist.size()+2 ); - envlist[pos++] = 0; - envlist[pos++] = 0; - } - char *applicationName; - if ( appName.isNull() ) - applicationName = 0; - else - applicationName = const_cast(appName.toLocal8Bit().data()); - success = CreateProcessA( applicationName, - const_cast(args.toLocal8Bit().data()), - 0, 0, TRUE, comms==0 ? CREATE_NEW_CONSOLE : DETACHED_PROCESS, - env==0 ? 0 : envlist.data(), - (const char*)QDir::toNativeSeparators(workingDir.absPath()).local8Bit(), - &startupInfo, d->pid ); -#endif // Q_OS_WINCE - } + , env == 0 ? 0 : envlist.data(), + (wchar_t*)QDir::toNativeSeparators(workingDir.absPath()).utf16(), + &startupInfo, d->pid ); + + free( applicationName ); + free( commandLine ); + if ( !success ) { d->deletePid(); return false; diff --git a/src/qt3support/widgets/q3datetimeedit.cpp b/src/qt3support/widgets/q3datetimeedit.cpp index b6e303c..4872642 100644 --- a/src/qt3support/widgets/q3datetimeedit.cpp +++ b/src/qt3support/widgets/q3datetimeedit.cpp @@ -114,39 +114,21 @@ static void readLocaleSettings() lTimeSep = new QString(); #if defined(Q_WS_WIN) - QT_WA({ - TCHAR data[10]; - GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDATE, data, 10); - *lDateSep = QString::fromUtf16((ushort*)data); - GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STIME, data, 10); - *lTimeSep = QString::fromUtf16((ushort*)data); - GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_ITIME, data, 10); - lAMPM = QString::fromUtf16((ushort*)data).toInt()==0; - GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_S1159, data, 10); - QString am = QString::fromUtf16((ushort*)data); - if (!am.isEmpty()) - lAM = new QString(am); - GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_S2359, data, 10); - QString pm = QString::fromUtf16((ushort*)data); - if (!pm.isEmpty() ) - lPM = new QString(pm); - } , { - char data[10]; - GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SDATE, (char*)&data, 10); - *lDateSep = QString::fromLocal8Bit(data); - GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_STIME, (char*)&data, 10); - *lTimeSep = QString::fromLocal8Bit(data); - GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_ITIME, (char*)&data, 10); - lAMPM = QString::fromLocal8Bit(data).toInt()==0; - GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_S1159, (char*)&data, 10); - QString am = QString::fromLocal8Bit(data); - if (!am.isEmpty()) - lAM = new QString(am); - GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_S2359, (char*)&data, 10); - QString pm = QString::fromLocal8Bit(data); - if (!pm.isEmpty()) - lPM = new QString(pm); - }); + wchar_t data[10]; + GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_SDATE, data, 10); + *lDateSep = QString::fromWCharArray(data); + GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STIME, data, 10); + *lTimeSep = QString::fromWCharArray(data); + GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_ITIME, data, 10); + lAMPM = QString::fromWCharArray(data).toInt() == 0; + GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_S1159, data, 10); + QString am = QString::fromWCharArray(data); + if (!am.isEmpty()) + lAM = new QString(am); + GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_S2359, data, 10); + QString pm = QString::fromWCharArray(data); + if (!pm.isEmpty() ) + lPM = new QString(pm); #else *lDateSep = QLatin1Char('-'); *lTimeSep = QLatin1Char(':'); diff --git a/src/qt3support/widgets/q3titlebar.cpp b/src/qt3support/widgets/q3titlebar.cpp index a05e4e5..ee3decf 100644 --- a/src/qt3support/widgets/q3titlebar.cpp +++ b/src/qt3support/widgets/q3titlebar.cpp @@ -173,35 +173,20 @@ void Q3TitleBarPrivate::readColors() bool colorsInitialized = false; #ifdef Q_WS_WIN // ask system properties on windows -#ifndef SPI_GETGRADIENTCAPTIONS -#define SPI_GETGRADIENTCAPTIONS 0x1008 -#endif -#ifndef COLOR_GRADIENTACTIVECAPTION -#define COLOR_GRADIENTACTIVECAPTION 27 -#endif -#ifndef COLOR_GRADIENTINACTIVECAPTION -#define COLOR_GRADIENTINACTIVECAPTION 28 -#endif if (QApplication::desktopSettingsAware()) { pal.setColor(QPalette::Active, QPalette::Highlight, colorref2qrgb(GetSysColor(COLOR_ACTIVECAPTION))); pal.setColor(QPalette::Inactive, QPalette::Highlight, colorref2qrgb(GetSysColor(COLOR_INACTIVECAPTION))); pal.setColor(QPalette::Active, QPalette::HighlightedText, colorref2qrgb(GetSysColor(COLOR_CAPTIONTEXT))); pal.setColor(QPalette::Inactive, QPalette::HighlightedText, colorref2qrgb(GetSysColor(COLOR_INACTIVECAPTIONTEXT))); - if (QSysInfo::WindowsVersion != QSysInfo::WV_95 && QSysInfo::WindowsVersion != QSysInfo::WV_NT) { - colorsInitialized = true; - BOOL gradient; - QT_WA({ - SystemParametersInfo(SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0); - } , { - SystemParametersInfoA(SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0); - }); - if (gradient) { - pal.setColor(QPalette::Active, QPalette::Base, colorref2qrgb(GetSysColor(COLOR_GRADIENTACTIVECAPTION))); - pal.setColor(QPalette::Inactive, QPalette::Base, colorref2qrgb(GetSysColor(COLOR_GRADIENTINACTIVECAPTION))); - } else { - pal.setColor(QPalette::Active, QPalette::Base, pal.color(QPalette::Active, QPalette::Highlight)); - pal.setColor(QPalette::Inactive, QPalette::Base, pal.color(QPalette::Inactive, QPalette::Highlight)); - } + colorsInitialized = true; + BOOL gradient = false; + SystemParametersInfo(SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0); + if (gradient) { + pal.setColor(QPalette::Active, QPalette::Base, colorref2qrgb(GetSysColor(COLOR_GRADIENTACTIVECAPTION))); + pal.setColor(QPalette::Inactive, QPalette::Base, colorref2qrgb(GetSysColor(COLOR_GRADIENTINACTIVECAPTION))); + } else { + pal.setColor(QPalette::Active, QPalette::Base, pal.color(QPalette::Active, QPalette::Highlight)); + pal.setColor(QPalette::Inactive, QPalette::Base, pal.color(QPalette::Inactive, QPalette::Highlight)); } } #endif // Q_WS_WIN -- cgit v0.12 From 70d033d033b34ed9c0dde38889062bfd8420366c Mon Sep 17 00:00:00 2001 From: Marius Storm-Olsen Date: Wed, 1 Jul 2009 11:50:13 +0200 Subject: src/testlib: LPCWSTR -> wchar_t* Merge-request: 604 Reviewed-by: Marius Storm-Olsen --- src/testlib/qplaintestlogger.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/testlib/qplaintestlogger.cpp b/src/testlib/qplaintestlogger.cpp index 3047326..071b55e 100644 --- a/src/testlib/qplaintestlogger.cpp +++ b/src/testlib/qplaintestlogger.cpp @@ -151,7 +151,7 @@ namespace QTest { int length = strlen(str); for (int pos = 0; pos < length; pos +=255) { QString uniText = QString::fromLatin1(str + pos, 255); - OutputDebugStringW((const LPCWSTR) uniText.utf16()); + OutputDebugString((wchar_t*)uniText.utf16()); } if (QTestLog::outputFileName()) #elif defined(Q_OS_WIN) -- cgit v0.12 From 7ae4e3c1827138cc47d14dd0f128b5999ccb30ce Mon Sep 17 00:00:00 2001 From: miniak Date: Wed, 1 Jul 2009 11:50:16 +0200 Subject: src/tools/idc: Remove QT_WA and non-Unicode code paths, dropping Win9x and NT support Merge-request: 604 Reviewed-by: Marius Storm-Olsen --- src/tools/idc/main.cpp | 69 ++++++++++++-------------------------------------- 1 file changed, 16 insertions(+), 53 deletions(-) diff --git a/src/tools/idc/main.cpp b/src/tools/idc/main.cpp index 48ce9cc..8fe8a70 100644 --- a/src/tools/idc/main.cpp +++ b/src/tools/idc/main.cpp @@ -40,7 +40,6 @@ ****************************************************************************/ #include -#include #include #include #include @@ -87,37 +86,19 @@ static bool runWithQtInEnvironment(const QString &cmd) static bool attachTypeLibrary(const QString &applicationName, int resource, const QByteArray &data, QString *errorMessage) { - HANDLE hExe = 0; - QT_WA({ - TCHAR *resourceName = MAKEINTRESOURCEW(resource); - hExe = BeginUpdateResourceW((TCHAR*)applicationName.utf16(), false); - if (hExe == 0) { - if (errorMessage) - *errorMessage = QString::fromLatin1("Failed to attach type library to binary %1 - could not open file.").arg(applicationName); - return false; - } - if (!UpdateResourceW(hExe,L"TYPELIB",resourceName,0,(void*)data.data(),data.count())) { - EndUpdateResource(hExe, true); - if (errorMessage) - *errorMessage = QString::fromLatin1("Failed to attach type library to binary %1 - could not update file.").arg(applicationName); - return false; - } - }, { - char *resourceName = MAKEINTRESOURCEA(resource); - hExe = BeginUpdateResourceA(applicationName.toLocal8Bit(), false); - if (hExe == 0) { - if (errorMessage) - *errorMessage = QString::fromLatin1("Failed to attach type library to binary %1 - could not open file.").arg(applicationName); - return false; - } - if (!UpdateResourceA(hExe,"TYPELIB",resourceName,0,(void*)data.data(),data.count())) { - EndUpdateResource(hExe, true); - if (errorMessage) - *errorMessage = QString::fromLatin1("Failed to attach type library to binary %1 - could not update file.").arg(applicationName); - return false; - } - }); - + HANDLE hExe = BeginUpdateResource((const wchar_t *)applicationName.utf16(), false); + if (hExe == 0) { + if (errorMessage) + *errorMessage = QString::fromLatin1("Failed to attach type library to binary %1 - could not open file.").arg(applicationName); + return false; + } + if (!UpdateResource(hExe, L"TYPELIB", MAKEINTRESOURCE(resource), 0, (void*)data.data(), data.count())) { + EndUpdateResource(hExe, true); + if (errorMessage) + *errorMessage = QString::fromLatin1("Failed to attach type library to binary %1 - could not update file.").arg(applicationName); + return false; + } + if (!EndUpdateResource(hExe,false)) { if (errorMessage) *errorMessage = QString::fromLatin1("Failed to attach type library to binary %1 - could not write file.").arg(applicationName); @@ -135,12 +116,7 @@ static bool registerServer(const QString &input) if (input.endsWith(QLatin1String(".exe"))) { ok = runWithQtInEnvironment(quotePath(input) + QLatin1String(" -regserver")); } else { - HMODULE hdll = 0; - QT_WA({ - hdll = LoadLibraryW((TCHAR*)input.utf16()); - }, { - hdll = LoadLibraryA(input.toLocal8Bit()); - }); + HMODULE hdll = LoadLibrary((const wchar_t *)input.utf16()); if (!hdll) { fprintf(stderr, "Couldn't load library file %s\n", (const char*)input.toLocal8Bit().data()); return false; @@ -162,12 +138,7 @@ static bool unregisterServer(const QString &input) if (input.endsWith(QLatin1String(".exe"))) { ok = runWithQtInEnvironment(quotePath(input) + QLatin1String(" -unregserver")); } else { - HMODULE hdll = 0; - QT_WA({ - hdll = LoadLibraryW((TCHAR*)input.utf16()); - }, { - hdll = LoadLibraryA(input.toLocal8Bit()); - }); + HMODULE hdll = LoadLibrary((const wchar_t *)input.utf16()); if (!hdll) { fprintf(stderr, "Couldn't load library file %s\n", (const char*)input.toLocal8Bit().data()); return false; @@ -191,12 +162,7 @@ static HRESULT dumpIdl(const QString &input, const QString &idlfile, const QStri if (runWithQtInEnvironment(quotePath(input) + QLatin1String(" -dumpidl ") + idlfile + QLatin1String(" -version ") + version)) res = S_OK; } else { - HMODULE hdll = 0; - QT_WA({ - hdll = LoadLibraryW((TCHAR*)input.utf16()); - }, { - hdll = LoadLibraryA(input.toLocal8Bit()); - }); + HMODULE hdll = LoadLibrary((const wchar_t *)input.utf16()); if (!hdll) { fprintf(stderr, "Couldn't load library file %s\n", (const char*)input.toLocal8Bit().data()); return 3; @@ -254,9 +220,6 @@ int runIdc(int argc, char **argv) else version = QLatin1String(argv[i]); } else if (p == QLatin1String("/tlb") || p == QLatin1String("-tlb")) { - if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) - fprintf(stderr, "IDC requires Windows NT/2000/XP!\n"); - ++i; if (i > argc) { error = QLatin1String("Missing name for type library file!"); -- cgit v0.12 From 24e7a5f983ead3fe722703851cf59cd0943e3964 Mon Sep 17 00:00:00 2001 From: miniak Date: Wed, 1 Jul 2009 11:50:19 +0200 Subject: src/3rdparty/phonon: Remove QT_WA and non-Unicode code paths, dropping Win9x and NT support Merge-request: 604 Reviewed-by: Marius Storm-Olsen --- src/3rdparty/phonon/ds9/qaudiocdreader.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/3rdparty/phonon/ds9/qaudiocdreader.cpp b/src/3rdparty/phonon/ds9/qaudiocdreader.cpp index b9f9fd6..d5bdce2 100644 --- a/src/3rdparty/phonon/ds9/qaudiocdreader.cpp +++ b/src/3rdparty/phonon/ds9/qaudiocdreader.cpp @@ -154,10 +154,7 @@ namespace Phonon path = QString::fromLatin1("\\\\.\\%1:").arg(drive); } - m_cddrive = QT_WA_INLINE ( - ::CreateFile( (TCHAR*)path.utf16(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL ), - ::CreateFileA( path.toLocal8Bit().constData(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL ) - ); + m_cddrive = ::CreateFile((const wchar_t *)path.utf16(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); qMemSet(m_toc, 0, sizeof(CDROM_TOC)); //read the TOC -- cgit v0.12 From 5ea86cfac34f65b2321ceeeb651e4e7099bf59a0 Mon Sep 17 00:00:00 2001 From: miniak Date: Wed, 1 Jul 2009 11:50:23 +0200 Subject: tools: Remove QT_WA and non-Unicode code paths, dropping Win9x and NT support Also QString::fromUtf16() -> QString::fromWCharArray() Merge-request: 604 Reviewed-by: Marius Storm-Olsen --- tools/activeqt/dumpcpp/main.cpp | 6 +- tools/configure/configure.pro | 2 +- tools/configure/configureapp.cpp | 19 +- tools/configure/environment.cpp | 218 ++++++--------------- tools/configure/tools.cpp | 4 +- .../src/plugins/activeqt/qaxwidgettaskmenu.cpp | 2 +- tools/linguist/shared/profileevaluator.cpp | 4 +- .../qtestlib/wince/cetest/activesyncconnection.cpp | 10 +- tools/xmlpatterns/main.cpp | 2 +- 9 files changed, 78 insertions(+), 189 deletions(-) diff --git a/tools/activeqt/dumpcpp/main.cpp b/tools/activeqt/dumpcpp/main.cpp index 0a4aa06..de3ec57 100644 --- a/tools/activeqt/dumpcpp/main.cpp +++ b/tools/activeqt/dumpcpp/main.cpp @@ -969,7 +969,7 @@ bool generateTypeLibrary(const QByteArray &typeLib, const QByteArray &outname, O QString libName; BSTR nameString; typelib->GetDocumentation(-1, &nameString, 0, 0, 0); - libName = QString::fromUtf16((const ushort *)nameString); + libName = QString::fromWCharArray(nameString); SysFreeString(nameString); if (!nameSpace.isEmpty()) libName = QString(nameSpace); @@ -1086,7 +1086,7 @@ bool generateTypeLibrary(const QByteArray &typeLib, const QByteArray &outname, O BSTR bstr; if (S_OK != typeinfo->GetDocumentation(-1, &bstr, 0, 0, 0)) break; - className = QString::fromUtf16((const ushort *)bstr).toLatin1(); + className = QString::fromWCharArray(bstr).toLatin1(); SysFreeString(bstr); switch (typekind) { case TKIND_RECORD: @@ -1227,7 +1227,7 @@ bool generateTypeLibrary(const QByteArray &typeLib, const QByteArray &outname, O BSTR bstr; if (S_OK != typeinfo->GetDocumentation(-1, &bstr, 0, 0, 0)) break; - className = QString::fromUtf16((const ushort *)bstr).toLatin1(); + className = QString::fromWCharArray(bstr).toLatin1(); SysFreeString(bstr); declOut << "// stub for vtable-only interface" << endl; diff --git a/tools/configure/configure.pro b/tools/configure/configure.pro index 1ce9a1b..fdeab29 100644 --- a/tools/configure/configure.pro +++ b/tools/configure/configure.pro @@ -3,7 +3,7 @@ DESTDIR = ../.. CONFIG += console flat CONFIG -= moc qt -DEFINES = QT_NODLL QT_NO_CODECS QT_NO_TEXTCODEC QT_NO_UNICODETABLES QT_LITE_COMPONENT QT_NO_STL QT_NO_COMPRESS QT_BUILD_QMAKE QT_NO_THREAD QT_NO_QOBJECT _CRT_SECURE_NO_DEPRECATE +DEFINES = UNICODE QT_NODLL QT_NO_CODECS QT_NO_TEXTCODEC QT_NO_UNICODETABLES QT_LITE_COMPONENT QT_NO_STL QT_NO_COMPRESS QT_BUILD_QMAKE QT_NO_THREAD QT_NO_QOBJECT _CRT_SECURE_NO_DEPRECATE win32 : LIBS += -lole32 -ladvapi32 diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index 597cd0e..509444b 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -116,16 +116,9 @@ Configure::Configure( int& argc, char** argv ) // Get the path to the executable - QFileInfo sourcePathInfo; - QT_WA({ - unsigned short module_name[256]; - GetModuleFileNameW(0, reinterpret_cast(module_name), sizeof(module_name)); - sourcePathInfo = QString::fromUtf16(module_name); - }, { - char module_name[256]; - GetModuleFileNameA(0, module_name, sizeof(module_name)); - sourcePathInfo = QString::fromLocal8Bit(module_name); - }); + wchar_t module_name[MAX_PATH]; + GetModuleFileName(0, module_name, sizeof(module_name) / sizeof(wchar_t)); + QFileInfo sourcePathInfo = QString::fromWCharArray(module_name); sourcePath = sourcePathInfo.absolutePath(); sourceDir = sourcePathInfo.dir(); buildPath = QDir::currentPath(); @@ -2733,7 +2726,7 @@ void Configure::generateConfigfiles() tmpFile.flush(); // Replace old qconfig.h with new one - ::SetFileAttributesA(outName.toLocal8Bit(), FILE_ATTRIBUTE_NORMAL); + ::SetFileAttributes((wchar_t*)outName.utf16(), FILE_ATTRIBUTE_NORMAL); QFile::remove(outName); tmpFile.copy(outName); tmpFile.close(); @@ -2769,7 +2762,7 @@ void Configure::generateConfigfiles() } outName = defSpec + "/qmake.conf"; - ::SetFileAttributesA(outName.toLocal8Bit(), FILE_ATTRIBUTE_NORMAL ); + ::SetFileAttributes((wchar_t*)outName.utf16(), FILE_ATTRIBUTE_NORMAL ); QFile qmakeConfFile(outName); if (qmakeConfFile.open(QFile::Append | QFile::WriteOnly | QFile::Text)) { QTextStream qmakeConfStream; @@ -2837,7 +2830,7 @@ void Configure::generateConfigfiles() tmpFile2.flush(); // Replace old qconfig.cpp with new one - ::SetFileAttributesA(outName.toLocal8Bit(), FILE_ATTRIBUTE_NORMAL ); + ::SetFileAttributes((wchar_t*)outName.utf16(), FILE_ATTRIBUTE_NORMAL ); QFile::remove( outName ); tmpFile2.copy(outName); tmpFile2.close(); diff --git a/tools/configure/environment.cpp b/tools/configure/environment.cpp index 6dc8940..b4c61f8 100644 --- a/tools/configure/environment.cpp +++ b/tools/configure/environment.cpp @@ -146,26 +146,14 @@ QString Environment::readRegistryKey(HKEY parentHandle, const QString &rSubkey) QString rSubkeyPath = keyPath(rSubkey); HKEY handle = 0; - LONG res; - QT_WA( { - res = RegOpenKeyExW(parentHandle, (WCHAR*)rSubkeyPath.utf16(), - 0, KEY_READ, &handle); - } , { - res = RegOpenKeyExA(parentHandle, rSubkeyPath.toLocal8Bit(), - 0, KEY_READ, &handle); - } ); - + LONG res = RegOpenKeyEx(parentHandle, (wchar_t*)rSubkeyPath.utf16(), 0, KEY_READ, &handle); if (res != ERROR_SUCCESS) return QString(); // get the size and type of the value DWORD dataType; DWORD dataSize; - QT_WA( { - res = RegQueryValueExW(handle, (WCHAR*)rSubkeyName.utf16(), 0, &dataType, 0, &dataSize); - }, { - res = RegQueryValueExA(handle, rSubkeyName.toLocal8Bit(), 0, &dataType, 0, &dataSize); - } ); + res = RegQueryValueEx(handle, (wchar_t*)rSubkeyName.utf16(), 0, &dataType, 0, &dataSize); if (res != ERROR_SUCCESS) { RegCloseKey(handle); return QString(); @@ -173,13 +161,8 @@ QString Environment::readRegistryKey(HKEY parentHandle, const QString &rSubkey) // get the value QByteArray data(dataSize, 0); - QT_WA( { - res = RegQueryValueExW(handle, (WCHAR*)rSubkeyName.utf16(), 0, 0, - reinterpret_cast(data.data()), &dataSize); - }, { - res = RegQueryValueExA(handle, rSubkeyName.toLocal8Bit(), 0, 0, - reinterpret_cast(data.data()), &dataSize); - } ); + res = RegQueryValueEx(handle, (wchar_t*)rSubkeyName.utf16(), 0, 0, + reinterpret_cast(data.data()), &dataSize); if (res != ERROR_SUCCESS) { RegCloseKey(handle); return QString(); @@ -189,11 +172,7 @@ QString Environment::readRegistryKey(HKEY parentHandle, const QString &rSubkey) switch (dataType) { case REG_EXPAND_SZ: case REG_SZ: { - QT_WA( { - result = QString::fromUtf16(((const ushort*)data.constData())); - }, { - result = QString::fromLatin1(data.constData()); - } ); + result = QString::fromWCharArray(((const wchar_t *)data.constData())); break; } @@ -201,29 +180,20 @@ QString Environment::readRegistryKey(HKEY parentHandle, const QString &rSubkey) QStringList l; int i = 0; for (;;) { - QString s; - QT_WA( { - s = QString::fromUtf16((const ushort*)data.constData() + i); - }, { - s = QString::fromLatin1(data.constData() + i); - } ); + QString s = QString::fromWCharArray((const wchar_t *)data.constData() + i); i += s.length() + 1; if (s.isEmpty()) break; l.append(s); } - result = l.join(", "); + result = l.join(", "); break; } case REG_NONE: case REG_BINARY: { - QT_WA( { - result = QString::fromUtf16((const ushort*)data.constData(), data.size()/2); - }, { - result = QString::fromLatin1(data.constData(), data.size()); - } ); + result = QString::fromWCharArray((const wchar_t *)data.constData(), data.size() / 2); break; } @@ -232,7 +202,7 @@ QString Environment::readRegistryKey(HKEY parentHandle, const QString &rSubkey) Q_ASSERT(data.size() == sizeof(int)); int i; memcpy((char*)&i, data.constData(), sizeof(int)); - result = QString::number(i); + result = QString::number(i); break; } @@ -350,29 +320,14 @@ bool Environment::detectExecutable(const QString &executable) PROCESS_INFORMATION procInfo; memset(&procInfo, 0, sizeof(procInfo)); - bool couldExecute; - QT_WA({ - // Unicode version - STARTUPINFOW startInfo; - memset(&startInfo, 0, sizeof(startInfo)); - startInfo.cb = sizeof(startInfo); - - couldExecute = CreateProcessW(0, (WCHAR*)executable.utf16(), - 0, 0, false, - CREATE_NO_WINDOW | CREATE_SUSPENDED, - 0, 0, &startInfo, &procInfo); - - }, { - // Ansi version - STARTUPINFOA startInfo; - memset(&startInfo, 0, sizeof(startInfo)); - startInfo.cb = sizeof(startInfo); + STARTUPINFO startInfo; + memset(&startInfo, 0, sizeof(startInfo)); + startInfo.cb = sizeof(startInfo); - couldExecute = CreateProcessA(0, executable.toLocal8Bit().data(), + bool couldExecute = CreateProcess(0, (wchar_t*)executable.utf16(), 0, 0, false, CREATE_NO_WINDOW | CREATE_SUSPENDED, 0, 0, &startInfo, &procInfo); - }) if (couldExecute) { CloseHandle(procInfo.hThread); @@ -421,61 +376,38 @@ static QString qt_create_commandline(const QString &program, const QStringList & } /*! - Creates a QByteArray of the \a environment in either UNICODE or - ansi representation. + Creates a QByteArray of the \a environment. */ static QByteArray qt_create_environment(const QStringList &environment) { QByteArray envlist; - if (!environment.isEmpty()) { - int pos = 0; - // add PATH if necessary (for DLL loading) - QByteArray path = qgetenv("PATH"); - QT_WA({ - if (environment.filter(QRegExp("^PATH=",Qt::CaseInsensitive)).isEmpty() - && !path.isNull()) { - QString tmp = QString(QLatin1String("PATH=%1")).arg(QString::fromLocal8Bit(path)); - uint tmpSize = sizeof(TCHAR) * (tmp.length()+1); - envlist.resize(envlist.size() + tmpSize ); - memcpy(envlist.data()+pos, tmp.utf16(), tmpSize); - pos += tmpSize; - } - // add the user environment - for (QStringList::ConstIterator it = environment.begin(); it != environment.end(); it++ ) { - QString tmp = *it; - uint tmpSize = sizeof(TCHAR) * (tmp.length()+1); - envlist.resize(envlist.size() + tmpSize); - memcpy(envlist.data()+pos, tmp.utf16(), tmpSize); - pos += tmpSize; - } - // add the 2 terminating 0 (actually 4, just to be on the safe side) - envlist.resize( envlist.size()+4 ); - envlist[pos++] = 0; - envlist[pos++] = 0; - envlist[pos++] = 0; - envlist[pos++] = 0; - }, { - if (environment.filter(QRegExp("^PATH=",Qt::CaseInsensitive)).isEmpty() && !path.isNull()) { - QByteArray tmp = QString("PATH=%1").arg(QString::fromLocal8Bit(path)).toLocal8Bit(); - uint tmpSize = tmp.length() + 1; - envlist.resize(envlist.size() + tmpSize); - memcpy(envlist.data()+pos, tmp.data(), tmpSize); - pos += tmpSize; - } - // add the user environment - for (QStringList::ConstIterator it = environment.begin(); it != environment.end(); it++) { - QByteArray tmp = (*it).toLocal8Bit(); - uint tmpSize = tmp.length() + 1; - envlist.resize(envlist.size() + tmpSize); - memcpy(envlist.data()+pos, tmp.data(), tmpSize); - pos += tmpSize; - } - // add the terminating 0 (actually 2, just to be on the safe side) - envlist.resize(envlist.size()+2); - envlist[pos++] = 0; - envlist[pos++] = 0; - }) + if (environment.isEmpty()) + return envlist; + + int pos = 0; + // add PATH if necessary (for DLL loading) + QByteArray path = qgetenv("PATH"); + if (environment.filter(QRegExp("^PATH=",Qt::CaseInsensitive)).isEmpty() && !path.isNull()) { + QString tmp = QString(QLatin1String("PATH=%1")).arg(QString::fromLocal8Bit(path)); + uint tmpSize = sizeof(wchar_t) * (tmp.length() + 1); + envlist.resize(envlist.size() + tmpSize); + memcpy(envlist.data() + pos, tmp.utf16(), tmpSize); + pos += tmpSize; } + // add the user environment + for (QStringList::ConstIterator it = environment.begin(); it != environment.end(); it++ ) { + QString tmp = *it; + uint tmpSize = sizeof(wchar_t) * (tmp.length() + 1); + envlist.resize(envlist.size() + tmpSize); + memcpy(envlist.data() + pos, tmp.utf16(), tmpSize); + pos += tmpSize; + } + // add the 2 terminating 0 (actually 4, just to be on the safe side) + envlist.resize(envlist.size() + 4); + envlist[pos++] = 0; + envlist[pos++] = 0; + envlist[pos++] = 0; + envlist[pos++] = 0; return envlist; } @@ -501,46 +433,24 @@ int Environment::execute(QStringList arguments, const QStringList &additionalEnv qDebug() << " " << additionalEnv; qDebug() << " " << removeEnv; #endif -// GetEnvironmentStrings is defined to GetEnvironmentStringsW when -// UNICODE is defined. We cannot use that, since we need to -// destinguish between unicode and ansi versions of the functions. -#if defined(UNICODE) && defined(GetEnvironmentStrings) -#undef GetEnvironmentStrings -#endif - // Create the full environment from the current environment and // the additionalEnv strings, then remove all variables defined // in removeEnv QMap fullEnvMap; - QT_WA({ - LPWSTR envStrings = GetEnvironmentStringsW(); - if (envStrings) { - int strLen = 0; - for (LPWSTR envString = envStrings; *(envString); envString += strLen + 1) { - strLen = wcslen(envString); - QString str = QString((const QChar*)envString, strLen); - if (!str.startsWith("=")) { // These are added by the system - int sepIndex = str.indexOf('='); - fullEnvMap.insert(str.left(sepIndex).toUpper(), str.mid(sepIndex +1)); - } - } - } - FreeEnvironmentStringsW(envStrings); - }, { - LPSTR envStrings = GetEnvironmentStrings(); - if (envStrings) { - int strLen = 0; - for (LPSTR envString = envStrings; *(envString); envString += strLen + 1) { - strLen = strlen(envString); - QString str = QLatin1String(envString); - if (!str.startsWith("=")) { // These are added by the system - int sepIndex = str.indexOf('='); - fullEnvMap.insert(str.left(sepIndex).toUpper(), str.mid(sepIndex +1)); - } + LPWSTR envStrings = GetEnvironmentStrings(); + if (envStrings) { + int strLen = 0; + for (LPWSTR envString = envStrings; *(envString); envString += strLen + 1) { + strLen = wcslen(envString); + QString str = QString((const QChar*)envString, strLen); + if (!str.startsWith("=")) { // These are added by the system + int sepIndex = str.indexOf('='); + fullEnvMap.insert(str.left(sepIndex).toUpper(), str.mid(sepIndex +1)); } } - FreeEnvironmentStringsA(envStrings); - }) + } + FreeEnvironmentStrings(envStrings); + // Add additionalEnv variables for (int i = 0; i < additionalEnv.count(); ++i) { const QString &str = additionalEnv.at(i); @@ -569,28 +479,14 @@ int Environment::execute(QStringList arguments, const QStringList &additionalEnv PROCESS_INFORMATION procInfo; memset(&procInfo, 0, sizeof(procInfo)); - bool couldExecute; - QT_WA({ - // Unicode version - STARTUPINFOW startInfo; - memset(&startInfo, 0, sizeof(startInfo)); - startInfo.cb = sizeof(startInfo); + STARTUPINFO startInfo; + memset(&startInfo, 0, sizeof(startInfo)); + startInfo.cb = sizeof(startInfo); - couldExecute = CreateProcessW(0, (WCHAR*)args.utf16(), + bool couldExecute = CreateProcess(0, (wchar_t*)args.utf16(), 0, 0, true, CREATE_UNICODE_ENVIRONMENT, envlist.isEmpty() ? 0 : envlist.data(), 0, &startInfo, &procInfo); - }, { - // Ansi version - STARTUPINFOA startInfo; - memset(&startInfo, 0, sizeof(startInfo)); - startInfo.cb = sizeof(startInfo); - - couldExecute = CreateProcessA(0, args.toLocal8Bit().data(), - 0, 0, true, 0, - envlist.isEmpty() ? 0 : envlist.data(), - 0, &startInfo, &procInfo); - }) if (couldExecute) { WaitForSingleObject(procInfo.hProcess, INFINITE); @@ -654,7 +550,7 @@ bool Environment::cpdir(const QString &srcDir, const QString &destDir) #endif QFile::remove(destFile); intermediate = QFile::copy(entry.absoluteFilePath(), destFile); - SetFileAttributesA(destFile.toLocal8Bit(), FILE_ATTRIBUTE_NORMAL); + SetFileAttributes((wchar_t*)destFile.utf16(), FILE_ATTRIBUTE_NORMAL); } if(!intermediate) { qDebug() << "cpdir: Failure for " << entry.fileName() << entry.isDir(); diff --git a/tools/configure/tools.cpp b/tools/configure/tools.cpp index f60f72c..708a537 100644 --- a/tools/configure/tools.cpp +++ b/tools/configure/tools.cpp @@ -201,8 +201,8 @@ void Tools::checkLicense(QMap &dictionary, QMapRelease(); diff --git a/tools/linguist/shared/profileevaluator.cpp b/tools/linguist/shared/profileevaluator.cpp index ef59543..47c1ec2 100644 --- a/tools/linguist/shared/profileevaluator.cpp +++ b/tools/linguist/shared/profileevaluator.cpp @@ -1949,9 +1949,9 @@ QStringList ProFileEvaluator::Private::values(const QString &variableName, ret = QLatin1String("Windows"); } else if (type == QLatin1String("name")) { DWORD name_length = 1024; - TCHAR name[1024]; + wchar_t name[1024]; if (GetComputerName(name, &name_length)) - ret = QString::fromUtf16((ushort*)name, name_length); + ret = QString::fromWCharArray(name); } else if (type == QLatin1String("version") || type == QLatin1String("version_string")) { QSysInfo::WinVersion ver = QSysInfo::WindowsVersion; if (type == QLatin1String("version")) diff --git a/tools/qtestlib/wince/cetest/activesyncconnection.cpp b/tools/qtestlib/wince/cetest/activesyncconnection.cpp index f047b79..e8ca8f2 100644 --- a/tools/qtestlib/wince/cetest/activesyncconnection.cpp +++ b/tools/qtestlib/wince/cetest/activesyncconnection.cpp @@ -270,8 +270,8 @@ bool ActiveSyncConnection::copyDirectoryFromDevice(const QString &deviceSource, } do { - QString srcFile = deviceSource + "\\" + QString::fromUtf16(data.cFileName); - QString destFile = localDest + "\\" + QString::fromUtf16(data.cFileName); + QString srcFile = deviceSource + "\\" + QString::fromWCharArray(data.cFileName); + QString destFile = localDest + "\\" + QString::fromWCharArray(data.cFileName); if ((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { if (recursive && !copyDirectoryFromDevice(srcFile, destFile, recursive)) { wprintf(L"Copy of subdirectory(%s) failed\n", srcFile.utf16()); @@ -306,8 +306,8 @@ bool ActiveSyncConnection::copyDirectory(const QString &srcDirectory, const QStr } do { - QString srcFile = srcDirectory + "\\" + QString::fromUtf16(data.cFileName); - QString destFile = destDirectory + "\\" + QString::fromUtf16(data.cFileName); + QString srcFile = srcDirectory + "\\" + QString::fromWCharArray(data.cFileName); + QString destFile = destDirectory + "\\" + QString::fromWCharArray(data.cFileName); if ((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { if (recursive && !copyDirectory(srcFile, destFile, recursive)) { wprintf(L"Copy of subdirectory(%s) failed\n", srcFile.utf16()); @@ -341,7 +341,7 @@ bool ActiveSyncConnection::deleteDirectory(const QString &directory, bool recurs return false; do { - QString FileName = directory + "\\" + QString::fromUtf16(FindFileData.cFileName); + QString FileName = directory + "\\" + QString::fromWCharArray(FindFileData.cFileName); if((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { if (recursive) if (!deleteDirectory(FileName, recursive, failIfContentExists)) diff --git a/tools/xmlpatterns/main.cpp b/tools/xmlpatterns/main.cpp index a5c2c41..2405d5d 100644 --- a/tools/xmlpatterns/main.cpp +++ b/tools/xmlpatterns/main.cpp @@ -194,7 +194,7 @@ protected: /* If we don't open stdout in "binary" mode on Windows, it will translate * 0xA into 0xD 0xA. See Trolltech task 173619, for an example. */ _setmode(_fileno(stdout), _O_BINARY); - m_stdout = QT_WA_INLINE(_wfdopen(_fileno(stdout), L"wb"),_fdopen(_fileno(stdout), "wb")); + m_stdout = _wfdopen(_fileno(stdout), L"wb"); out->open(m_stdout, QIODevice::WriteOnly); #else out->open(stdout, QIODevice::WriteOnly); -- cgit v0.12 From c447ce31632e25fdd40404cc96b6980aa0adcef8 Mon Sep 17 00:00:00 2001 From: Marius Storm-Olsen Date: Wed, 1 Jul 2009 11:50:26 +0200 Subject: qmake: Remove QT_WA and non-Unicode code paths, dropping Win9x and NT support Also, QString::fromUtf16() -> QString::fromWCharArray() Merge-request: 604 Reviewed-by: Marius Storm-Olsen --- qmake/generators/win32/msvc_vcproj.cpp | 43 ++++++---------------------------- qmake/option.cpp | 13 +++------- qmake/project.cpp | 6 ++--- 3 files changed, 13 insertions(+), 49 deletions(-) diff --git a/qmake/generators/win32/msvc_vcproj.cpp b/qmake/generators/win32/msvc_vcproj.cpp index 079aa9f..50f78d7 100644 --- a/qmake/generators/win32/msvc_vcproj.cpp +++ b/qmake/generators/win32/msvc_vcproj.cpp @@ -120,14 +120,7 @@ static QString readRegistryKey(HKEY parentHandle, const QString &rSubkey) QString rSubkeyPath = keyPath(rSubkey); HKEY handle = 0; - LONG res; - QT_WA( { - res = RegOpenKeyExW(parentHandle, (WCHAR*)rSubkeyPath.utf16(), - 0, KEY_READ, &handle); - } , { - res = RegOpenKeyExA(parentHandle, rSubkeyPath.toLocal8Bit(), - 0, KEY_READ, &handle); - } ); + LONG res = RegOpenKeyEx(parentHandle, (wchar_t*)rSubkeyPath.utf16(), 0, KEY_READ, &handle); if (res != ERROR_SUCCESS) return QString(); @@ -135,11 +128,7 @@ static QString readRegistryKey(HKEY parentHandle, const QString &rSubkey) // get the size and type of the value DWORD dataType; DWORD dataSize; - QT_WA( { - res = RegQueryValueExW(handle, (WCHAR*)rSubkeyName.utf16(), 0, &dataType, 0, &dataSize); - }, { - res = RegQueryValueExA(handle, rSubkeyName.toLocal8Bit(), 0, &dataType, 0, &dataSize); - } ); + res = RegQueryValueEx(handle, (wchar_t*)rSubkeyName.utf16(), 0, &dataType, 0, &dataSize); if (res != ERROR_SUCCESS) { RegCloseKey(handle); return QString(); @@ -147,13 +136,8 @@ static QString readRegistryKey(HKEY parentHandle, const QString &rSubkey) // get the value QByteArray data(dataSize, 0); - QT_WA( { - res = RegQueryValueExW(handle, (WCHAR*)rSubkeyName.utf16(), 0, 0, - reinterpret_cast(data.data()), &dataSize); - }, { - res = RegQueryValueExA(handle, rSubkeyName.toLocal8Bit(), 0, 0, - reinterpret_cast(data.data()), &dataSize); - } ); + res = RegQueryValueEx(handle, (wchar_t*)rSubkeyName.utf16(), 0, 0, + reinterpret_cast(data.data()), &dataSize); if (res != ERROR_SUCCESS) { RegCloseKey(handle); return QString(); @@ -163,11 +147,7 @@ static QString readRegistryKey(HKEY parentHandle, const QString &rSubkey) switch (dataType) { case REG_EXPAND_SZ: case REG_SZ: { - QT_WA( { - result = QString::fromUtf16(((const ushort*)data.constData())); - }, { - result = QString::fromLatin1(data.constData()); - } ); + result = QString::fromWCharArray(((const wchar_t *)data.constData())); break; } @@ -175,12 +155,7 @@ static QString readRegistryKey(HKEY parentHandle, const QString &rSubkey) QStringList l; int i = 0; for (;;) { - QString s; - QT_WA( { - s = QString::fromUtf16((const ushort*)data.constData() + i); - }, { - s = QString::fromLatin1(data.constData() + i); - } ); + QString s = QString::fromWCharArray((const wchar_t *)data.constData() + i); i += s.length() + 1; if (s.isEmpty()) @@ -193,11 +168,7 @@ static QString readRegistryKey(HKEY parentHandle, const QString &rSubkey) case REG_NONE: case REG_BINARY: { - QT_WA( { - result = QString::fromUtf16((const ushort*)data.constData(), data.size()/2); - }, { - result = QString::fromLatin1(data.constData(), data.size()); - } ); + result = QString::fromWCharArray((const wchar_t *)data.constData(), data.size() / 2); break; } diff --git a/qmake/option.cpp b/qmake/option.cpp index 0e4a608..5f8c4f4 100644 --- a/qmake/option.cpp +++ b/qmake/option.cpp @@ -716,16 +716,9 @@ QString qmake_libraryInfoFile() { QString ret; #if defined( Q_OS_WIN ) - QFileInfo filePath; - QT_WA({ - unsigned short module_name[256]; - GetModuleFileNameW(0, reinterpret_cast(module_name), sizeof(module_name)); - filePath = QString::fromUtf16(module_name); - }, { - char module_name[256]; - GetModuleFileNameA(0, module_name, sizeof(module_name)); - filePath = QString::fromLocal8Bit(module_name); - }); + wchar_t module_name[MAX_PATH]; + GetModuleFileName(0, module_name, MAX_PATH); + QFileInfo filePath = QString::fromWCharArray(module_name); ret = filePath.filePath(); #else QString argv0 = QFile::decodeName(QByteArray(Option::application_argv0)); diff --git a/qmake/project.cpp b/qmake/project.cpp index 047a5e3..704d8a6 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -3117,9 +3117,9 @@ QStringList &QMakeProject::values(const QString &_var, QMap Date: Wed, 1 Jul 2009 11:50:29 +0200 Subject: tests: Remove QT_WA and non-Unicode code paths, dropping Win9x and NT support Merge-request: 604 Reviewed-by: Marius Storm-Olsen --- tests/auto/qaccessibility/tst_qaccessibility.cpp | 6 +- tests/auto/qapplication/tst_qapplication.cpp | 6 +- tests/auto/qdatetimeedit/tst_qdatetimeedit.cpp | 2 +- tests/auto/qfile/tst_qfile.cpp | 91 +++++----------- tests/auto/qfileinfo/tst_qfileinfo.cpp | 31 ++---- tests/auto/qitemview/tst_qitemview.cpp | 2 +- tests/auto/qlocale/tst_qlocale.cpp | 31 +----- tests/auto/qpixmap/tst_qpixmap.cpp | 7 +- tests/auto/qsettings/tst_qsettings.cpp | 6 -- tests/auto/qsharedmemory/src/qsystemlock_win.cpp | 26 ++--- tests/auto/qstring/tst_qstring.cpp | 8 +- tests/auto/qstyle/tst_qstyle.cpp | 2 +- tests/auto/qtcpserver/tst_qtcpserver.cpp | 120 +++++++++------------ tests/auto/qtimer/tst_qtimer.cpp | 2 +- tests/auto/qwidget/tst_qwidget.cpp | 8 +- .../qwineventnotifier/tst_qwineventnotifier.cpp | 7 +- .../auto/windowsmobile/test/tst_windowsmobile.cpp | 2 +- tests/benchmarks/qdiriterator/main.cpp | 2 +- .../qdiriterator/qfilesystemiterator.cpp | 19 +--- tests/benchmarks/qfile/main.cpp | 12 +-- 20 files changed, 133 insertions(+), 257 deletions(-) diff --git a/tests/auto/qaccessibility/tst_qaccessibility.cpp b/tests/auto/qaccessibility/tst_qaccessibility.cpp index a87d02f..8a88b59 100644 --- a/tests/auto/qaccessibility/tst_qaccessibility.cpp +++ b/tests/auto/qaccessibility/tst_qaccessibility.cpp @@ -53,12 +53,12 @@ #include "QtTest/qtestaccessible.h" #if defined(Q_OS_WINCE) -extern "C" bool SystemParametersInfoW(UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni); +extern "C" bool SystemParametersInfo(UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni); #define SPI_GETPLATFORMTYPE 257 inline bool IsValidCEPlatform() { wchar_t tszPlatform[64]; - if (SystemParametersInfoW(SPI_GETPLATFORMTYPE, sizeof(tszPlatform)/sizeof(*tszPlatform),tszPlatform,0)) { - QString platform = QString::fromUtf16(tszPlatform); + if (SystemParametersInfo(SPI_GETPLATFORMTYPE, sizeof(tszPlatform) / sizeof(*tszPlatform), tszPlatform, 0)) { + QString platform = QString::fromWCharArray(tszPlatform); if ((platform == QLatin1String("PocketPC")) || (platform == QLatin1String("Smartphone"))) return false; } diff --git a/tests/auto/qapplication/tst_qapplication.cpp b/tests/auto/qapplication/tst_qapplication.cpp index 2fa7584..85494af 100644 --- a/tests/auto/qapplication/tst_qapplication.cpp +++ b/tests/auto/qapplication/tst_qapplication.cpp @@ -755,9 +755,9 @@ void tst_QApplication::libraryPaths() // current Path. Therefore we need to identify it ourselves // here for the test. QFileInfo filePath; - wchar_t module_name[256]; - GetModuleFileNameW(0, module_name, sizeof(module_name) / sizeof(wchar_t)); - filePath = QString::fromUtf16((ushort *)module_name); + wchar_t module_name[MAX_PATH]; + GetModuleFileName(0, module_name, MAX_PATH); + filePath = QString::fromWCharArray(module_name); QString testDir = filePath.path() + "/test"; #endif QApplication::setLibraryPaths(QStringList() << testDir); diff --git a/tests/auto/qdatetimeedit/tst_qdatetimeedit.cpp b/tests/auto/qdatetimeedit/tst_qdatetimeedit.cpp index 6c73fd6..ab98d1d 100644 --- a/tests/auto/qdatetimeedit/tst_qdatetimeedit.cpp +++ b/tests/auto/qdatetimeedit/tst_qdatetimeedit.cpp @@ -102,7 +102,7 @@ Q_DECLARE_METATYPE(QList); #if defined(Q_OS_WINCE) bool qt_wince_is_platform(const QString &platformString) { - TCHAR tszPlatform[64]; + wchar_t tszPlatform[64]; if (SystemParametersInfo(SPI_GETPLATFORMTYPE, sizeof(tszPlatform)/sizeof(*tszPlatform),tszPlatform,0)) if (0 == _tcsicmp(reinterpret_cast (platformString.utf16()), tszPlatform)) diff --git a/tests/auto/qfile/tst_qfile.cpp b/tests/auto/qfile/tst_qfile.cpp index d7e9dff..8d9c2be 100644 --- a/tests/auto/qfile/tst_qfile.cpp +++ b/tests/auto/qfile/tst_qfile.cpp @@ -994,57 +994,32 @@ static QString getWorkingDirectoryForLink(const QString &linkFileName) { bool neededCoInit = false; QString ret; - QT_WA({ - IShellLink *psl; - HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl); - if (hres == CO_E_NOTINITIALIZED) { // COM was not initialized - neededCoInit = true; - CoInitialize(NULL); - hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl); - } - if (SUCCEEDED(hres)) { // Get pointer to the IPersistFile interface. - IPersistFile *ppf; - hres = psl->QueryInterface(IID_IPersistFile, (LPVOID *)&ppf); - if (SUCCEEDED(hres)) { - hres = ppf->Load((LPOLESTR)linkFileName.utf16(), STGM_READ); - //The original path of the link is retrieved. If the file/folder - //was moved, the return value still have the old path. - if(SUCCEEDED(hres)) { - wchar_t szGotPath[MAX_PATH]; - if (psl->GetWorkingDirectory(szGotPath, MAX_PATH) == NOERROR) - ret = QString::fromUtf16((ushort*)szGotPath); - } - ppf->Release(); - } - psl->Release(); - } - },{ - IShellLinkA *psl; - HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl); - if (hres == CO_E_NOTINITIALIZED) { // COM was not initialized - neededCoInit = true; - CoInitialize(NULL); - hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl); - } + IShellLink *psl; + HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl); + if (hres == CO_E_NOTINITIALIZED) { // COM was not initialized + neededCoInit = true; + CoInitialize(NULL); + hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl); + } - if (SUCCEEDED(hres)) { // Get pointer to the IPersistFile interface. - IPersistFile *ppf; - hres = psl->QueryInterface(IID_IPersistFile, (LPVOID *)&ppf); - if (SUCCEEDED(hres)) { - hres = ppf->Load((LPOLESTR)linkFileName.utf16(), STGM_READ); - //The original path of the link is retrieved. If the file/folder - //was moved, the return value still have the old path. - if(SUCCEEDED(hres)) { - char szGotPath[MAX_PATH]; - if (psl->GetWorkingDirectory(szGotPath, MAX_PATH) == NOERROR) - ret = QString::fromLocal8Bit(szGotPath); - } - ppf->Release(); + if (SUCCEEDED(hres)) { // Get pointer to the IPersistFile interface. + IPersistFile *ppf; + hres = psl->QueryInterface(IID_IPersistFile, (LPVOID *)&ppf); + if (SUCCEEDED(hres)) { + hres = ppf->Load((LPOLESTR)linkFileName.utf16(), STGM_READ); + //The original path of the link is retrieved. If the file/folder + //was moved, the return value still have the old path. + if(SUCCEEDED(hres)) { + wchar_t szGotPath[MAX_PATH]; + if (psl->GetWorkingDirectory(szGotPath, MAX_PATH) == NOERROR) + ret = QString::fromWCharArray(szGotPath); } - psl->Release(); + ppf->Release(); } - }); + psl->Release(); + } + if (neededCoInit) { CoUninitialize(); } @@ -1538,13 +1513,8 @@ void tst_QFile::largeFileSupport() qlonglong freespace = qlonglong(0); #ifdef Q_WS_WIN _ULARGE_INTEGER free; - if (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based) { - if (::GetDiskFreeSpaceExW((wchar_t *)QDir::currentPath().utf16(), &free, 0, 0)) - freespace = free.QuadPart; - } else { - if (::GetDiskFreeSpaceExA(QDir::currentPath().local8Bit(), &free, 0, 0)) - freespace = free.QuadPart; - } + if (::GetDiskFreeSpaceEx((wchar_t*)QDir::currentPath().utf16(), &free, 0, 0)) + freespace = free.QuadPart; if (freespace != 0) { #elif defined(Q_OS_IRIX) struct statfs info; @@ -1662,16 +1632,9 @@ void tst_QFile::longFileName() } { QFile file(fileName); -#if defined(Q_WS_WIN) -#if !defined(Q_OS_WINCE) - QT_WA({ if (false) ; }, { - QEXPECT_FAIL("244 chars", "Full pathname must be less than 260 chars", Abort); - QEXPECT_FAIL("244 chars to absolutepath", "Full pathname must be less than 260 chars", Abort); - }); -#else - QEXPECT_FAIL("244 chars", "Full pathname must be less than 260 chars", Abort); - QEXPECT_FAIL("244 chars to absolutepath", "Full pathname must be less than 260 chars", Abort); -#endif +#if defined(Q_OS_WINCE) + QEXPECT_FAIL("244 chars", "Full pathname must be less than 260 chars", Abort); + QEXPECT_FAIL("244 chars to absolutepath", "Full pathname must be less than 260 chars", Abort); #endif QVERIFY(file.open(QFile::WriteOnly | QFile::Text)); QTextStream ts(&file); diff --git a/tests/auto/qfileinfo/tst_qfileinfo.cpp b/tests/auto/qfileinfo/tst_qfileinfo.cpp index 1a73948..48dc357 100644 --- a/tests/auto/qfileinfo/tst_qfileinfo.cpp +++ b/tests/auto/qfileinfo/tst_qfileinfo.cpp @@ -862,11 +862,6 @@ void tst_QFileInfo::fileTimes() #if !defined(Q_OS_UNIX) && !defined(Q_OS_WINCE) QVERIFY(fileInfo.created() < beforeWrite); #endif -#ifdef Q_OS_WIN - if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) { - QVERIFY(fileInfo.lastRead().addDays(1) > beforeRead); - } else -#endif //In Vista the last-access timestamp is not updated when the file is accessed/touched (by default). //To enable this the HKLM\SYSTEM\CurrentControlSet\Control\FileSystem\NtfsDisableLastAccessUpdate //is set to 0, in the test machine. @@ -897,26 +892,14 @@ void tst_QFileInfo::fileTimes_oldFile() // WriteOnly can create files, ReadOnly cannot. DWORD creationDisp = OPEN_ALWAYS; - HANDLE fileHandle; - // Create the file handle. - QT_WA({ - fileHandle = CreateFileW(L"oldfile.txt", - accessRights, - shareMode, - &securityAtts, - creationDisp, - flagsAndAtts, - NULL); - }, { - fileHandle = CreateFileA("oldfile.txt", - accessRights, - shareMode, - &securityAtts, - creationDisp, - flagsAndAtts, - NULL); - }); + HANDLE fileHandle = CreateFile(L"oldfile.txt", + accessRights, + shareMode, + &securityAtts, + creationDisp, + flagsAndAtts, + NULL); // Set file times back to 1601. FILETIME ctime; diff --git a/tests/auto/qitemview/tst_qitemview.cpp b/tests/auto/qitemview/tst_qitemview.cpp index 6bfd1e8..73c08d1 100644 --- a/tests/auto/qitemview/tst_qitemview.cpp +++ b/tests/auto/qitemview/tst_qitemview.cpp @@ -55,7 +55,7 @@ #if defined(Q_OS_WINCE) bool qt_wince_is_platform(const QString &platformString) { - TCHAR tszPlatform[64]; + wchar_t tszPlatform[64]; if (SystemParametersInfo(SPI_GETPLATFORMTYPE, sizeof(tszPlatform)/sizeof(*tszPlatform),tszPlatform,0)) if (0 == _tcsicmp(reinterpret_cast (platformString.utf16()), tszPlatform)) diff --git a/tests/auto/qlocale/tst_qlocale.cpp b/tests/auto/qlocale/tst_qlocale.cpp index 8ac6ef0..9ef7f1d 100644 --- a/tests/auto/qlocale/tst_qlocale.cpp +++ b/tests/auto/qlocale/tst_qlocale.cpp @@ -1093,12 +1093,7 @@ void tst_QLocale::macDefaultLocale() static QString getWinLocaleInfo(LCTYPE type) { LCID id = GetThreadLocale(); - int cnt = 0; - QT_WA({ - cnt = GetLocaleInfoW(id, type, 0, 0)*2; - } , { - cnt = GetLocaleInfoA(id, type, 0, 0); - }); + int cnt = GetLocaleInfo(id, type, 0, 0) * 2; if (cnt == 0) { qWarning("QLocale: empty windows locale info (%d)", type); @@ -1107,38 +1102,20 @@ static QString getWinLocaleInfo(LCTYPE type) QByteArray buff(cnt, 0); - QT_WA({ - cnt = GetLocaleInfoW(id, type, - reinterpret_cast(buff.data()), - buff.size()/2); - } , { - cnt = GetLocaleInfoA(id, type, - buff.data(), buff.size()); - }); + cnt = GetLocaleInfo(id, type, reinterpret_cast(buff.data()), buff.size() / 2); if (cnt == 0) { qWarning("QLocale: empty windows locale info (%d)", type); return QString(); } - QString result; - QT_WA({ - result = QString::fromUtf16(reinterpret_cast(buff.data())); - } , { - result = QString::fromLocal8Bit(buff.data()); - }); - return result; + return QString::fromWCharArray(reinterpret_cast(buff.data())); } static void setWinLocaleInfo(LCTYPE type, const QString &value) { LCID id = GetThreadLocale(); - - QT_WA({ - SetLocaleInfoW(id, type, reinterpret_cast(value.utf16())); - } , { - SetLocaleInfoA(id, type, value.toLocal8Bit()); - }); + SetLocaleInfo(id, type, reinterpret_cast(value.utf16())); } class RestoreLocaleHelper { diff --git a/tests/auto/qpixmap/tst_qpixmap.cpp b/tests/auto/qpixmap/tst_qpixmap.cpp index f52d44e..b3736ab 100644 --- a/tests/auto/qpixmap/tst_qpixmap.cpp +++ b/tests/auto/qpixmap/tst_qpixmap.cpp @@ -854,12 +854,7 @@ void tst_QPixmap::toWinHBITMAP() BITMAP bitmap_info; memset(&bitmap_info, 0, sizeof(BITMAP)); - int res; - QT_WA({ - res = GetObjectW(bitmap, sizeof(BITMAP), &bitmap_info); - } , { - res = GetObjectA(bitmap, sizeof(BITMAP), &bitmap_info); - }); + int res = GetObject(bitmap, sizeof(BITMAP), &bitmap_info); QVERIFY(res); QCOMPARE(100, (int) bitmap_info.bmWidth); diff --git a/tests/auto/qsettings/tst_qsettings.cpp b/tests/auto/qsettings/tst_qsettings.cpp index f682d37..f0f446d 100644 --- a/tests/auto/qsettings/tst_qsettings.cpp +++ b/tests/auto/qsettings/tst_qsettings.cpp @@ -3010,12 +3010,6 @@ void tst_QSettings::oldWriteEntry_QString_QString() QSettings readSettings("software.org", "KillerAPP"); QFETCH( QString, s ); bool ok = FALSE; -#ifdef Q_OS_WIN - if (qWinVersion() & Qt::WV_DOS_based) { - QEXPECT_FAIL("data2", "Windows 9x does not support unicode characters in the registry", Abort); - QEXPECT_FAIL("data5", "Windows 9x does not support unicode characters in the registry", Abort); - } -#endif QCOMPARE( readSettings.readEntry( "/Trolltech/QSettingsTesting/String", QString::null, &ok ), s ); QVERIFY( ok ); } diff --git a/tests/auto/qsharedmemory/src/qsystemlock_win.cpp b/tests/auto/qsharedmemory/src/qsystemlock_win.cpp index 94d90ce..a50b77b 100644 --- a/tests/auto/qsharedmemory/src/qsystemlock_win.cpp +++ b/tests/auto/qsharedmemory/src/qsystemlock_win.cpp @@ -75,32 +75,24 @@ HANDLE QSystemLockPrivate::handle() // Create it if it doesn't already exists. if (semaphore == 0) { QString safeName = makeKeyFileName(); - QT_WA({ - semaphore = CreateSemaphoreW(0, MAX_LOCKS, MAX_LOCKS, (TCHAR*)safeName.utf16()); - }, { - semaphore = CreateSemaphoreA(0, MAX_LOCKS, MAX_LOCKS, safeName.toLocal8Bit().constData()); - }); + semaphore = CreateSemaphore(0, MAX_LOCKS, MAX_LOCKS, (wchar_t*)safeName.utf16()); if (semaphore == 0) { setErrorString(QLatin1String("QSystemLockPrivate::handle")); - return 0; - } + return 0; + } } if (semaphoreLock == 0) { - QString safeLockName = QSharedMemoryPrivate::makePlatformSafeKey(key + QLatin1String("lock"), QLatin1String("qipc_systemlock_")); - QT_WA({ - semaphoreLock = CreateSemaphoreW(0, - 1, 1, (TCHAR*)safeLockName.utf16()); - }, { - semaphoreLock = CreateSemaphoreA(0, - 1, 1, safeLockName.toLocal8Bit().constData()); - }); + QString safeLockName = QSharedMemoryPrivate::makePlatformSafeKey(key + QLatin1String("lock"), QLatin1String("qipc_systemlock_")); + semaphoreLock = CreateSemaphore(0, 1, 1, (wchar_t*)safeLockName.utf16()); + if (semaphoreLock == 0) { setErrorString(QLatin1String("QSystemLockPrivate::handle")); - return 0; - } + return 0; + } } + return semaphore; } diff --git a/tests/auto/qstring/tst_qstring.cpp b/tests/auto/qstring/tst_qstring.cpp index e172c33..85dbda0 100644 --- a/tests/auto/qstring/tst_qstring.cpp +++ b/tests/auto/qstring/tst_qstring.cpp @@ -3997,15 +3997,15 @@ void tst_QString::localeAwareCompare() # if defined(Q_OS_WINCE) DWORD oldLcid = GetUserDefaultLCID(); SetUserDefaultLCID(locale); - if (locale != GetUserDefaultLCID()) { + + QCOMPARE(locale, GetUserDefaultLCID()); # else DWORD oldLcid = GetThreadLocale(); SetThreadLocale(locale); - if (locale != GetThreadLocale()) { + QCOMPARE(locale, GetThreadLocale()); # endif - QSKIP("SetThreadLocale() not supported on Win9x", SkipSingle); - } + #elif defined (Q_WS_MAC) QSKIP("Setting the locale is not supported on OS X (you can set the C locale, but that won't affect CFStringCompare which is used to compare strings)", SkipAll); #else diff --git a/tests/auto/qstyle/tst_qstyle.cpp b/tests/auto/qstyle/tst_qstyle.cpp index 4009e66..2cb5080 100644 --- a/tests/auto/qstyle/tst_qstyle.cpp +++ b/tests/auto/qstyle/tst_qstyle.cpp @@ -91,7 +91,7 @@ #include static bool qt_wince_is_smartphone() { - TCHAR tszPlatform[64]; + wchar_t tszPlatform[64]; if (SystemParametersInfo(SPI_GETPLATFORMTYPE, sizeof(tszPlatform)/sizeof(*tszPlatform),tszPlatform,0)) if (0 == _tcsicmp(reinterpret_cast (QString::fromLatin1("Smartphone").utf16()), tszPlatform)) diff --git a/tests/auto/qtcpserver/tst_qtcpserver.cpp b/tests/auto/qtcpserver/tst_qtcpserver.cpp index a06c871..5c82cbb 100644 --- a/tests/auto/qtcpserver/tst_qtcpserver.cpp +++ b/tests/auto/qtcpserver/tst_qtcpserver.cpp @@ -274,42 +274,35 @@ void tst_QTcpServer::ipv4LoopbackPerformanceTest() QTcpSocket *clientB = server.nextPendingConnection(); QVERIFY(clientB); -#if defined(Q_WS_WIN) - if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) { - QSKIP("Dont run performance tests on QSysInfo::WV_DOS_based systems, overloads the system", SkipAll); - } else -#endif - { - QByteArray buffer(16384, '@'); - QTime stopWatch; - stopWatch.start(); - qlonglong totalWritten = 0; - while (stopWatch.elapsed() < 5000) { - QVERIFY(clientA.write(buffer.data(), buffer.size()) > 0); - clientA.flush(); - totalWritten += buffer.size(); - while (clientB->waitForReadyRead(100)) { - if (clientB->bytesAvailable() == 16384) - break; - } - clientB->read(buffer.data(), buffer.size()); - clientB->write(buffer.data(), buffer.size()); - clientB->flush(); - totalWritten += buffer.size(); - while (clientA.waitForReadyRead(100)) { - if (clientA.bytesAvailable() == 16384) - break; - } - clientA.read(buffer.data(), buffer.size()); + QByteArray buffer(16384, '@'); + QTime stopWatch; + stopWatch.start(); + qlonglong totalWritten = 0; + while (stopWatch.elapsed() < 5000) { + QVERIFY(clientA.write(buffer.data(), buffer.size()) > 0); + clientA.flush(); + totalWritten += buffer.size(); + while (clientB->waitForReadyRead(100)) { + if (clientB->bytesAvailable() == 16384) + break; } + clientB->read(buffer.data(), buffer.size()); + clientB->write(buffer.data(), buffer.size()); + clientB->flush(); + totalWritten += buffer.size(); + while (clientA.waitForReadyRead(100)) { + if (clientA.bytesAvailable() == 16384) + break; + } + clientA.read(buffer.data(), buffer.size()); + } - qDebug("\t\t%s: %.1fMB/%.1fs: %.1fMB/s", - server.serverAddress().toString().toLatin1().constData(), - totalWritten / (1024.0 * 1024.0), - stopWatch.elapsed() / 1000.0, - (totalWritten / (stopWatch.elapsed() / 1000.0)) / (1024 * 1024)); + qDebug("\t\t%s: %.1fMB/%.1fs: %.1fMB/s", + server.serverAddress().toString().toLatin1().constData(), + totalWritten / (1024.0 * 1024.0), + stopWatch.elapsed() / 1000.0, + (totalWritten / (stopWatch.elapsed() / 1000.0)) / (1024 * 1024)); - } delete clientB; } @@ -378,42 +371,35 @@ void tst_QTcpServer::ipv4PerformanceTest() QTcpSocket *clientB = server.nextPendingConnection(); QVERIFY(clientB); -#if defined(Q_WS_WIN) - if (QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based) { - QSKIP("Dont run performance tests on QSysInfo::WV_DOS_based systems, overloads the system", SkipAll); - } else -#endif - { - - QByteArray buffer(16384, '@'); - QTime stopWatch; - stopWatch.start(); - qlonglong totalWritten = 0; - while (stopWatch.elapsed() < 5000) { - qlonglong writtenA = clientA.write(buffer.data(), buffer.size()); - clientA.flush(); - totalWritten += buffer.size(); - while (clientB->waitForReadyRead(100)) { - if (clientB->bytesAvailable() == writtenA) - break; - } - clientB->read(buffer.data(), buffer.size()); - qlonglong writtenB = clientB->write(buffer.data(), buffer.size()); - clientB->flush(); - totalWritten += buffer.size(); - while (clientA.waitForReadyRead(100)) { - if (clientA.bytesAvailable() == writtenB) - break; - } - clientA.read(buffer.data(), buffer.size()); + QByteArray buffer(16384, '@'); + QTime stopWatch; + stopWatch.start(); + qlonglong totalWritten = 0; + while (stopWatch.elapsed() < 5000) { + qlonglong writtenA = clientA.write(buffer.data(), buffer.size()); + clientA.flush(); + totalWritten += buffer.size(); + while (clientB->waitForReadyRead(100)) { + if (clientB->bytesAvailable() == writtenA) + break; } - - qDebug("\t\t%s: %.1fMB/%.1fs: %.1fMB/s", - probeSocket.localAddress().toString().toLatin1().constData(), - totalWritten / (1024.0 * 1024.0), - stopWatch.elapsed() / 1000.0, - (totalWritten / (stopWatch.elapsed() / 1000.0)) / (1024 * 1024)); + clientB->read(buffer.data(), buffer.size()); + qlonglong writtenB = clientB->write(buffer.data(), buffer.size()); + clientB->flush(); + totalWritten += buffer.size(); + while (clientA.waitForReadyRead(100)) { + if (clientA.bytesAvailable() == writtenB) + break; + } + clientA.read(buffer.data(), buffer.size()); } + + qDebug("\t\t%s: %.1fMB/%.1fs: %.1fMB/s", + probeSocket.localAddress().toString().toLatin1().constData(), + totalWritten / (1024.0 * 1024.0), + stopWatch.elapsed() / 1000.0, + (totalWritten / (stopWatch.elapsed() / 1000.0)) / (1024 * 1024)); + delete clientB; } diff --git a/tests/auto/qtimer/tst_qtimer.cpp b/tests/auto/qtimer/tst_qtimer.cpp index 5fb62a5..43b7553 100644 --- a/tests/auto/qtimer/tst_qtimer.cpp +++ b/tests/auto/qtimer/tst_qtimer.cpp @@ -253,7 +253,7 @@ void tst_QTimer::livelock() QEXPECT_FAIL("non-zero timer", "", Continue); #elif defined(Q_OS_WIN) if (QSysInfo::WindowsVersion < QSysInfo::WV_XP) - QEXPECT_FAIL("non-zero timer", "Multimedia timers are not available on Win2K/9x", Continue); + QEXPECT_FAIL("non-zero timer", "Multimedia timers are not available on Windows 2000", Continue); #endif QVERIFY(tester.postEventAtRightTime); } diff --git a/tests/auto/qwidget/tst_qwidget.cpp b/tests/auto/qwidget/tst_qwidget.cpp index 1430146..04ec77d 100644 --- a/tests/auto/qwidget/tst_qwidget.cpp +++ b/tests/auto/qwidget/tst_qwidget.cpp @@ -106,7 +106,7 @@ // taken from qguifunctions_wce.cpp #define SPI_GETPLATFORMTYPE 257 bool qt_wince_is_platform(const QString &platformString) { - TCHAR tszPlatform[64]; + wchar_t tszPlatform[64]; if (SystemParametersInfo(SPI_GETPLATFORMTYPE, sizeof(tszPlatform)/sizeof(*tszPlatform),tszPlatform,0)) if (0 == _tcsicmp(reinterpret_cast (platformString.utf16()), tszPlatform)) @@ -3433,9 +3433,9 @@ static QString visibleWindowTitle(QWidget *window, Qt::WindowState state = Qt::W #ifdef Q_WS_WIN Q_UNUSED(state); const size_t maxTitleLength = 256; - WCHAR title[maxTitleLength]; - GetWindowTextW(window->winId(), title, maxTitleLength); - vTitle = QString::fromUtf16((ushort *)title); + wchar_t title[maxTitleLength]; + GetWindowText(window->winId(), title, maxTitleLength); + vTitle = QString::fromWCharArray(title); #elif defined(Q_WS_X11) /* We can't check what the window manager displays, but we can diff --git a/tests/auto/qwineventnotifier/tst_qwineventnotifier.cpp b/tests/auto/qwineventnotifier/tst_qwineventnotifier.cpp index 24d28c5..4b00773 100644 --- a/tests/auto/qwineventnotifier/tst_qwineventnotifier.cpp +++ b/tests/auto/qwineventnotifier/tst_qwineventnotifier.cpp @@ -110,12 +110,9 @@ void tst_QWinEventNotifier::simple_timerSet() void tst_QWinEventNotifier::simple() { - QT_WA({ - simpleHEvent = CreateEventW(0, TRUE, FALSE, 0); - }, { - simpleHEvent = CreateEventA(0, TRUE, FALSE, 0); - }); + simpleHEvent = CreateEvent(0, TRUE, FALSE, 0); QVERIFY(simpleHEvent); + QWinEventNotifier n(simpleHEvent); QObject::connect(&n, SIGNAL(activated(HANDLE)), this, SLOT(simple_activated())); simpleActivated = false; diff --git a/tests/auto/windowsmobile/test/tst_windowsmobile.cpp b/tests/auto/windowsmobile/test/tst_windowsmobile.cpp index 8c7c021..654e19f 100644 --- a/tests/auto/windowsmobile/test/tst_windowsmobile.cpp +++ b/tests/auto/windowsmobile/test/tst_windowsmobile.cpp @@ -72,7 +72,7 @@ public: #ifdef Q_OS_WINCE_WM bool qt_wince_is_platform(const QString &platformString) { - TCHAR tszPlatform[64]; + wchar_t tszPlatform[64]; if (SystemParametersInfo(SPI_GETPLATFORMTYPE, sizeof(tszPlatform)/sizeof(*tszPlatform),tszPlatform,0)) if (0 == _tcsicmp(reinterpret_cast (platformString.utf16()), tszPlatform)) diff --git a/tests/benchmarks/qdiriterator/main.cpp b/tests/benchmarks/qdiriterator/main.cpp index 13128f7..1a5ffbb 100644 --- a/tests/benchmarks/qdiriterator/main.cpp +++ b/tests/benchmarks/qdiriterator/main.cpp @@ -107,7 +107,7 @@ static int posix_helper(const wchar_t *dirpath) wchar_t appendedPath[MAX_PATH]; wcscpy(appendedPath, dirpath); wcscat(appendedPath, L"\\*"); - hSearch = FindFirstFileW(appendedPath, &fd); + hSearch = FindFirstFile(appendedPath, &fd); appendedPath[origDirPathLength] = 0; if (hSearch == INVALID_HANDLE_VALUE) { diff --git a/tests/benchmarks/qdiriterator/qfilesystemiterator.cpp b/tests/benchmarks/qdiriterator/qfilesystemiterator.cpp index 1ef600b..47720f1 100644 --- a/tests/benchmarks/qdiriterator/qfilesystemiterator.cpp +++ b/tests/benchmarks/qdiriterator/qfilesystemiterator.cpp @@ -108,17 +108,6 @@ QT_BEGIN_NAMESPACE -#ifdef Q_OS_WIN -inline QString convertString(TCHAR* sz) -{ -#ifdef UNICODE - return QString::fromUtf16(sz); -#else - return QString::fromLocal8Bit(sz); -#endif -} -#endif - class QFileSystemIteratorPrivate { public: @@ -202,7 +191,7 @@ QFileSystemIteratorPrivate::~QFileSystemIteratorPrivate() } #ifdef Q_OS_WIN -static bool isDotOrDotDot(const TCHAR* name) +static bool isDotOrDotDot(const wchar_t* name) { if (name[0] == L'.' && name[1] == 0) return true; @@ -339,7 +328,7 @@ bool QFileSystemIteratorPrivate::advanceHelper() if (m_entry->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { QByteArray ba = m_dirPaths.top(); ba += '\\'; - ba += convertString(m_entry->cFileName); + ba += QString::fromWCharArray(m_entry->cFileName); pushSubDirectory(ba); } #else @@ -634,7 +623,7 @@ QString QFileSystemIterator::fileName() const if (d->m_currentDirShown == QFileSystemIteratorPrivate::ShowDotDotDir) return QLatin1String("@@"); #ifdef Q_OS_WIN - return convertString(d->m_entry->cFileName); + return QString::fromWCharArray(d->m_entry->cFileName); #else return QString::fromLocal8Bit(d->m_entry->d_name); #endif @@ -659,7 +648,7 @@ QString QFileSystemIterator::filePath() const else if (d->m_entry) { ba += '/'; #ifdef Q_OS_WIN - ba += convertString(d->m_entry->cFileName); + ba += QString::fromWCharArray(d->m_entry->cFileName); #else ba += d->m_entry->d_name; #endif diff --git a/tests/benchmarks/qfile/main.cpp b/tests/benchmarks/qfile/main.cpp index 2fa425d..5360eb5 100644 --- a/tests/benchmarks/qfile/main.cpp +++ b/tests/benchmarks/qfile/main.cpp @@ -275,11 +275,11 @@ void tst_qfile::readBigFile() HANDLE hndl; // ensure we don't account string conversion - TCHAR* cfilename = (TCHAR*)filename.utf16(); + wchar_t* cfilename = (wchar_t*)filename.utf16(); hndl = CreateFile(cfilename, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); Q_ASSERT(hndl); - TCHAR* nativeBuffer = new TCHAR[BUFSIZE]; + wchar_t* nativeBuffer = new wchar_t[BUFSIZE]; DWORD numberOfBytesRead; QBENCHMARK { @@ -358,7 +358,7 @@ void tst_qfile::seek() HANDLE hndl; // ensure we don't account string conversion - TCHAR* cfilename = (TCHAR*)filename.utf16(); + wchar_t* cfilename = (wchar_t*)filename.utf16(); hndl = CreateFile(cfilename, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); Q_ASSERT(hndl); @@ -441,7 +441,7 @@ void tst_qfile::open() HANDLE hndl; // ensure we don't account string conversion - TCHAR* cfilename = (TCHAR*)filename.utf16(); + wchar_t* cfilename = (wchar_t*)filename.utf16(); QBENCHMARK { hndl = CreateFile(cfilename, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); @@ -620,11 +620,11 @@ void tst_qfile::readSmallFiles() HANDLE hndl; // ensure we don't account string conversion - TCHAR* cfilename = (TCHAR*)filename.utf16(); + wchar_t* cfilename = (wchar_t*)filename.utf16(); hndl = CreateFile(cfilename, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0); Q_ASSERT(hndl); - TCHAR* nativeBuffer = new TCHAR[BUFSIZE]; + wchar_t* nativeBuffer = new wchar_t[BUFSIZE]; DWORD numberOfBytesRead; QBENCHMARK { do { -- cgit v0.12 From a69160c5f4ef146f5e9922161bcff9c6fed213c7 Mon Sep 17 00:00:00 2001 From: Marius Storm-Olsen Date: Wed, 1 Jul 2009 11:50:33 +0200 Subject: examples: QString::fromUtf16() -> QString::fromWCharArray() Merge-request: 604 Reviewed-by: Marius Storm-Olsen --- examples/activeqt/dotnet/wrapper/lib/tools.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/activeqt/dotnet/wrapper/lib/tools.cpp b/examples/activeqt/dotnet/wrapper/lib/tools.cpp index 856b5c8..eac2d78 100644 --- a/examples/activeqt/dotnet/wrapper/lib/tools.cpp +++ b/examples/activeqt/dotnet/wrapper/lib/tools.cpp @@ -56,6 +56,6 @@ String *QStringToString(const QString &qstring) QString StringToQString(String *string) { const wchar_t __pin *chars = PtrToStringChars(string); - return QString::fromUtf16((const ushort *)chars); + return QString::fromWCharArray(chars); } //! [1] -- cgit v0.12 From a6e32ae1c84984041107a83db9307caffbda9849 Mon Sep 17 00:00:00 2001 From: Marius Storm-Olsen Date: Wed, 1 Jul 2009 11:50:36 +0200 Subject: Make the macros QT_WA & QT_WA_INLINE only use the unicode part Merge-request: 604 Reviewed-by: Marius Storm-Olsen --- src/corelib/global/qglobal.h | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 00a9466..a522bcf 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -1420,17 +1420,9 @@ inline QT3_SUPPORT bool qt_winUnicode() { return true; } inline QT3_SUPPORT int qWinVersion() { return QSysInfo::WindowsVersion; } #endif -#ifdef Q_OS_WINCE -#define QT_WA(uni, ansi) uni -#define QT_WA_INLINE(uni, ansi) (uni) -#elif defined(UNICODE) -#define QT_WA(uni, ansi) if (!(QSysInfo::windowsVersion() & QSysInfo::WV_DOS_based)) { uni } else { ansi } +#define QT_WA(unicode, ansi) unicode +#define QT_WA_INLINE(unicode, ansi) (unicode) -#define QT_WA_INLINE(uni, ansi) (!(QSysInfo::windowsVersion() & QSysInfo::WV_DOS_based) ? uni : ansi) -#else -#define QT_WA(uni, ansi) ansi -#define QT_WA_INLINE(uni, ansi) ansi -#endif #endif /* Q_WS_WIN */ #ifndef Q_OUTOFLINE_TEMPLATE -- cgit v0.12 From 8a8c9a2f668bedc7dd7ecf1f4f025a1587ca9fc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Luthi?= Date: Wed, 1 Jul 2009 12:03:52 +0200 Subject: Fix a few typos Merge-request: 788 Reviewed-by: Norwegian Rock Cat --- src/gui/kernel/qapplication_mac.mm | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/gui/kernel/qapplication_mac.mm b/src/gui/kernel/qapplication_mac.mm index ad9f220..e7d5a79 100644 --- a/src/gui/kernel/qapplication_mac.mm +++ b/src/gui/kernel/qapplication_mac.mm @@ -1069,7 +1069,7 @@ void qt_init(QApplicationPrivate *priv, int) if (GetCurrentProcess(&psn) == noErr) { // Jambi needs to transform itself since most people aren't "used" // to putting things in bundles, but other people may actually not - // want to tranform the process (running as a helper or somethng) + // want to tranform the process (running as a helper or something) // so don't do that for them. This means checking both LSUIElement // and LSBackgroundOnly. If you set them both... well, you // shouldn't do that. @@ -1760,7 +1760,7 @@ QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event if(window) { HIViewRef hiview; if(HIViewGetViewForMouseEvent(HIViewGetRoot(window), event, &hiview) == noErr) { - widget = QWidget::find((WId)hiview);; + widget = QWidget::find((WId)hiview); if (widget) { // Make sure we didn't pass over a widget with a "fake hole" in it. QWidget *otherWidget = QApplication::widgetAt(where.h, where.v); @@ -1878,8 +1878,8 @@ QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event QMacTabletHash *tabletHash = qt_mac_tablet_hash(); if (!tabletHash->contains(tabletPointRec.deviceID)) { - qWarning("QCocoaView handleTabletEvent: This tablet device is unknown" - " (received no proximity event for it). Discarding event."); + qWarning("handleTabletEvent: This tablet device is unknown" + " (received no proximity event for it). Discarding event."); return false; } QTabletDeviceData &deviceData = tabletHash->operator[](tabletPointRec.deviceID); @@ -1922,7 +1922,7 @@ QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event QApplication::sendSpontaneousEvent(widget, &e); if (e.isAccepted()) { #if defined(DEBUG_MOUSE_MAPS) - qDebug("Bail out early due to table acceptance"); + qDebug("Bail out early due to tablet acceptance"); #endif break; } -- cgit v0.12 From 82e825ed841bce324a6892fcbace03f9936d4f4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Luthi?= Date: Wed, 1 Jul 2009 12:03:54 +0200 Subject: Fix tablet events Tablet events should set the qt_button_down, otherwise if the tablet moves onto a widget that does not accept a tablet event, it will set qt_button_down and effectively "grab" the mouse. However, we should only do this if we accept the tablet event. Merge-request: 788 Reviewed-by: Norwegian Rock Cat --- src/gui/kernel/qapplication_mac.mm | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/gui/kernel/qapplication_mac.mm b/src/gui/kernel/qapplication_mac.mm index e7d5a79..04f4cc9 100644 --- a/src/gui/kernel/qapplication_mac.mm +++ b/src/gui/kernel/qapplication_mac.mm @@ -1921,6 +1921,11 @@ QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event tp, rotation, z, modifiers, deviceData.tabletUniqueID); QApplication::sendSpontaneousEvent(widget, &e); if (e.isAccepted()) { + if (t == QEvent::TabletPress) { + qt_button_down = widget; + } else if (t == QEvent::TabletRelease) { + qt_button_down = 0; + } #if defined(DEBUG_MOUSE_MAPS) qDebug("Bail out early due to tablet acceptance"); #endif -- cgit v0.12 From 3618227de7036a091ea8187a20434470c0c792dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Luthi?= Date: Wed, 1 Jul 2009 12:03:55 +0200 Subject: Never discard TabletRelease events as they may be delivered *after* TabletLeaveProximity events Merge-request: 788 Reviewed-by: Norwegian Rock Cat --- src/gui/kernel/qapplication_mac.mm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gui/kernel/qapplication_mac.mm b/src/gui/kernel/qapplication_mac.mm index 04f4cc9..ce4e422 100644 --- a/src/gui/kernel/qapplication_mac.mm +++ b/src/gui/kernel/qapplication_mac.mm @@ -1877,7 +1877,8 @@ QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event tablet_button_state = new_tablet_button_state; QMacTabletHash *tabletHash = qt_mac_tablet_hash(); - if (!tabletHash->contains(tabletPointRec.deviceID)) { + if (!tabletHash->contains(tabletPointRec.deviceID) && t != QEvent::TabletRelease) { + // Never discard TabletRelease events as they may be delivered *after* TabletLeaveProximity events qWarning("handleTabletEvent: This tablet device is unknown" " (received no proximity event for it). Discarding event."); return false; -- cgit v0.12 From ac8e76bc6d7cc3dbb1e64949bc6034697d9d9ba1 Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Wed, 1 Jul 2009 12:29:26 +0200 Subject: doc: Changed wording in some stub callbacks. --- src/xml/sax/qxml.cpp | 52 ++++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/xml/sax/qxml.cpp b/src/xml/sax/qxml.cpp index d776cc4..6be6988 100644 --- a/src/xml/sax/qxml.cpp +++ b/src/xml/sax/qxml.cpp @@ -2403,7 +2403,7 @@ events are reported. /*! \reimp - Does nothing. + This reimplementation does nothing. */ void QXmlDefaultHandler::setDocumentLocator(QXmlLocator*) { @@ -2412,7 +2412,7 @@ void QXmlDefaultHandler::setDocumentLocator(QXmlLocator*) /*! \reimp - Does nothing. + This reimplementation does nothing. */ bool QXmlDefaultHandler::startDocument() { @@ -2422,7 +2422,7 @@ bool QXmlDefaultHandler::startDocument() /*! \reimp - Does nothing. + This reimplementation does nothing. */ bool QXmlDefaultHandler::endDocument() { @@ -2432,7 +2432,7 @@ bool QXmlDefaultHandler::endDocument() /*! \reimp - Does nothing. + This reimplementation does nothing. */ bool QXmlDefaultHandler::startPrefixMapping(const QString&, const QString&) { @@ -2442,7 +2442,7 @@ bool QXmlDefaultHandler::startPrefixMapping(const QString&, const QString&) /*! \reimp - Does nothing. + This reimplementation does nothing. */ bool QXmlDefaultHandler::endPrefixMapping(const QString&) { @@ -2452,7 +2452,7 @@ bool QXmlDefaultHandler::endPrefixMapping(const QString&) /*! \reimp - Does nothing. + This reimplementation does nothing. */ bool QXmlDefaultHandler::startElement(const QString&, const QString&, const QString&, const QXmlAttributes&) @@ -2463,7 +2463,7 @@ bool QXmlDefaultHandler::startElement(const QString&, const QString&, /*! \reimp - Does nothing. + This reimplementation does nothing. */ bool QXmlDefaultHandler::endElement(const QString&, const QString&, const QString&) @@ -2474,7 +2474,7 @@ bool QXmlDefaultHandler::endElement(const QString&, const QString&, /*! \reimp - Does nothing. + This reimplementation does nothing. */ bool QXmlDefaultHandler::characters(const QString&) { @@ -2484,7 +2484,7 @@ bool QXmlDefaultHandler::characters(const QString&) /*! \reimp - Does nothing. + This reimplementation does nothing. */ bool QXmlDefaultHandler::ignorableWhitespace(const QString&) { @@ -2494,7 +2494,7 @@ bool QXmlDefaultHandler::ignorableWhitespace(const QString&) /*! \reimp - Does nothing. + This reimplementation does nothing. */ bool QXmlDefaultHandler::processingInstruction(const QString&, const QString&) @@ -2505,7 +2505,7 @@ bool QXmlDefaultHandler::processingInstruction(const QString&, /*! \reimp - Does nothing. + This reimplementation does nothing. */ bool QXmlDefaultHandler::skippedEntity(const QString&) { @@ -2515,7 +2515,7 @@ bool QXmlDefaultHandler::skippedEntity(const QString&) /*! \reimp - Does nothing. + This reimplementation does nothing. */ bool QXmlDefaultHandler::warning(const QXmlParseException&) { @@ -2525,7 +2525,7 @@ bool QXmlDefaultHandler::warning(const QXmlParseException&) /*! \reimp - Does nothing. + This reimplementation does nothing. */ bool QXmlDefaultHandler::error(const QXmlParseException&) { @@ -2535,7 +2535,7 @@ bool QXmlDefaultHandler::error(const QXmlParseException&) /*! \reimp - Does nothing. + This reimplementation does nothing. */ bool QXmlDefaultHandler::fatalError(const QXmlParseException&) { @@ -2545,7 +2545,7 @@ bool QXmlDefaultHandler::fatalError(const QXmlParseException&) /*! \reimp - Does nothing. + This reimplementation does nothing. */ bool QXmlDefaultHandler::notationDecl(const QString&, const QString&, const QString&) @@ -2556,7 +2556,7 @@ bool QXmlDefaultHandler::notationDecl(const QString&, const QString&, /*! \reimp - Does nothing. + This reimplementation does nothing. */ bool QXmlDefaultHandler::unparsedEntityDecl(const QString&, const QString&, const QString&, const QString&) @@ -2590,7 +2590,7 @@ QString QXmlDefaultHandler::errorString() const /*! \reimp - Does nothing. + This reimplementation does nothing. */ bool QXmlDefaultHandler::startDTD(const QString&, const QString&, const QString&) { @@ -2600,7 +2600,7 @@ bool QXmlDefaultHandler::startDTD(const QString&, const QString&, const QString& /*! \reimp - Does nothing. + This reimplementation does nothing. */ bool QXmlDefaultHandler::endDTD() { @@ -2610,7 +2610,7 @@ bool QXmlDefaultHandler::endDTD() /*! \reimp - Does nothing. + This reimplementation does nothing. */ bool QXmlDefaultHandler::startEntity(const QString&) { @@ -2620,7 +2620,7 @@ bool QXmlDefaultHandler::startEntity(const QString&) /*! \reimp - Does nothing. + This reimplementation does nothing. */ bool QXmlDefaultHandler::endEntity(const QString&) { @@ -2630,7 +2630,7 @@ bool QXmlDefaultHandler::endEntity(const QString&) /*! \reimp - Does nothing. + This reimplementation does nothing. */ bool QXmlDefaultHandler::startCDATA() { @@ -2640,7 +2640,7 @@ bool QXmlDefaultHandler::startCDATA() /*! \reimp - Does nothing. + This reimplementation does nothing. */ bool QXmlDefaultHandler::endCDATA() { @@ -2650,7 +2650,7 @@ bool QXmlDefaultHandler::endCDATA() /*! \reimp - Does nothing. + This reimplementation does nothing. */ bool QXmlDefaultHandler::comment(const QString&) { @@ -2660,7 +2660,7 @@ bool QXmlDefaultHandler::comment(const QString&) /*! \reimp - Does nothing. + This reimplementation does nothing. */ bool QXmlDefaultHandler::attributeDecl(const QString&, const QString&, const QString&, const QString&, const QString&) { @@ -2670,7 +2670,7 @@ bool QXmlDefaultHandler::attributeDecl(const QString&, const QString&, const QSt /*! \reimp - Does nothing. + This reimplementation does nothing. */ bool QXmlDefaultHandler::internalEntityDecl(const QString&, const QString&) { @@ -2680,7 +2680,7 @@ bool QXmlDefaultHandler::internalEntityDecl(const QString&, const QString&) /*! \reimp - Does nothing. + This reimplementation does nothing. */ bool QXmlDefaultHandler::externalEntityDecl(const QString&, const QString&, const QString&) { -- cgit v0.12 From d43a10d6d9a5f13fc8deac052926720927e09e83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 1 Jul 2009 13:53:41 +0200 Subject: Compiler warnings. --- src/gui/graphicsview/qgraphicsitem.cpp | 2 ++ src/gui/graphicsview/qgraphicsproxywidget.cpp | 1 - src/gui/graphicsview/qgraphicsscene.cpp | 2 +- src/gui/kernel/qwidget.cpp | 2 ++ 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index e8ed97f..2223f5d 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -6329,6 +6329,8 @@ void QGraphicsItem::releaseGesture(int gestureId) */ void QGraphicsItem::setGestureEnabled(int gestureId, bool enable) { + Q_UNUSED(gestureId); + Q_UNUSED(enable); //### } diff --git a/src/gui/graphicsview/qgraphicsproxywidget.cpp b/src/gui/graphicsview/qgraphicsproxywidget.cpp index ab94679..f081222 100644 --- a/src/gui/graphicsview/qgraphicsproxywidget.cpp +++ b/src/gui/graphicsview/qgraphicsproxywidget.cpp @@ -878,7 +878,6 @@ bool QGraphicsProxyWidget::event(QEvent *event) case QEvent::GraphicsSceneGesture: { qDebug() << "QGraphicsProxyWidget: graphicsscenegesture"; if (d->widget && d->widget->isVisible()) { - QGraphicsSceneGestureEvent *ge = static_cast(event); //### TODO: widget->childAt(): decompose gesture event and find widget under hotspots. //QGestureManager::instance()->sendGestureEvent(d->widget, ge->gestures().toSet(), ge->cancelledGestures()); return true; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index d790640..e50ee94 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -4122,7 +4122,6 @@ void QGraphicsScenePrivate::sendGestureEvent(const QSet &gestures, co continue; } QGesturePrivate *gd = g->d_func(); - QGraphicsItem *item = gd->graphicsItem; gd->graphicsItem = 0; //### THIS IS BS, DONT FORGET TO REWRITE THIS CODE @@ -6042,6 +6041,7 @@ void QGraphicsScenePrivate::grabGesture(QGraphicsItem *item, int gestureId) void QGraphicsScenePrivate::releaseGesture(QGraphicsItem *item, int gestureId) { + Q_UNUSED(gestureId); itemsWithGestures.remove(item); //### } diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 1b31318..9a834aa 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -11110,6 +11110,8 @@ void QWidget::releaseGesture(int gestureId) */ void QWidget::setGestureEnabled(int gestureId, bool enable) { + Q_UNUSED(gestureId); + Q_UNUSED(enable); //### } -- cgit v0.12 From 7bf505a54379388b292df528114d6e2dd8d9d4d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Trond=20Kjern=C3=A5sen?= Date: Wed, 1 Jul 2009 13:55:16 +0200 Subject: Fixed cleanup of glyph cache textures in the GL 2 engine. This could potentially crash when a context was destroyed before the actual font engine holding the QGLTextureGlyphCache was destroyed. Reviewed-by: Samuel --- .../gl2paintengineex/qpaintengineex_opengl2.cpp | 29 +++++++++++++++++++--- src/opengl/qgl_p.h | 4 +++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 4bf5d4c..edc7c44 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -88,8 +88,9 @@ static const GLuint QT_IMAGE_TEXTURE_UNIT = 0; //Can be the same as brush static const GLuint QT_MASK_TEXTURE_UNIT = 1; static const GLuint QT_BACKGROUND_TEXTURE_UNIT = 2; -class QGLTextureGlyphCache : public QTextureGlyphCache +class QGLTextureGlyphCache : public QObject, public QTextureGlyphCache { + Q_OBJECT public: QGLTextureGlyphCache(QGLContext *context, QFontEngineGlyphCache::Type type, const QTransform &matrix); ~QGLTextureGlyphCache(); @@ -105,6 +106,24 @@ public: inline void setPaintEnginePrivate(QGL2PaintEngineExPrivate *p) { pex = p; } + +public Q_SLOTS: + void contextDestroyed(const QGLContext *context) { + if (context == ctx) { + QList shares = qgl_share_reg()->shares(ctx); + if (shares.isEmpty()) { + glDeleteFramebuffers(1, &m_fbo); + if (m_width || m_height) + glDeleteTextures(1, &m_texture); + } else { + // since the context holding the texture is shared, and + // about to be destroyed, we have to transfer ownership + // of the texture to one of the share contexts + ctx = const_cast(shares.at(0)); + } + } + } + private: QGLContext *ctx; @@ -126,6 +145,8 @@ QGLTextureGlyphCache::QGLTextureGlyphCache(QGLContext *context, QFontEngineGlyph , m_height(0) { glGenFramebuffers(1, &m_fbo); + connect(QGLSignalProxy::instance(), SIGNAL(aboutToDestroyContext(const QGLContext *)), + SLOT(contextDestroyed(const QGLContext *))); } QGLTextureGlyphCache::~QGLTextureGlyphCache() @@ -251,7 +272,7 @@ QGL2PaintEngineExPrivate::~QGL2PaintEngineExPrivate() void QGL2PaintEngineExPrivate::updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform, GLuint id) { // glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT); //### Is it always this texture unit? - if (id != -1 && id == lastTexture) + if (id != GLuint(-1) && id == lastTexture) return; lastTexture = id; @@ -1408,7 +1429,7 @@ void QGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op) if (state()->matrix.type() <= QTransform::TxScale) { rect = state()->matrix.mapRect(rect); - if (d->use_system_clip && rect.contains(d->systemClip.boundingRect()) + if ((d->use_system_clip && rect.contains(d->systemClip.boundingRect())) || rect.contains(QRect(0, 0, d->width, d->height))) return; } @@ -1606,3 +1627,5 @@ QOpenGL2PaintEngineState::~QOpenGL2PaintEngineState() } QT_END_NAMESPACE + +#include "qpaintengineex_opengl2.moc" diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index 85e9bd7..ac19d64 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -421,6 +421,10 @@ public: removeShare(oldContext); } + QList shares(const QGLContext *context) { + return reg.values(context); + } + private: QGLSharingHash reg; }; -- cgit v0.12 From 145e17f6cc405dd935451f0151b1a8a451c78f71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 1 Jul 2009 14:01:54 +0200 Subject: Compiler warning. --- src/gui/graphicsview/qgraphicsscene.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 9de6598..8fdf651 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -297,8 +297,8 @@ QGraphicsScenePrivate::QGraphicsScenePrivate() allItemsIgnoreHoverEvents(true), allItemsUseDefaultCursor(true), painterStateProtection(true), - style(0), sortCacheEnabled(false), + style(0), allItemsIgnoreTouchEvents(true) { } -- cgit v0.12 From 66a281ab76303074cd9cbb6cd22dcc5f3dbe8454 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Wed, 1 Jul 2009 14:40:51 +0200 Subject: Made QPainter / OpenGL intermixing in hellogl_es2 work properly again. Need to call syncState() to let the paint engine set depth clipping state parameters back to their OpenGL defaults. Reviewed-by: Trond --- examples/opengl/hellogl_es2/glwidget.cpp | 3 +++ src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/examples/opengl/hellogl_es2/glwidget.cpp b/examples/opengl/hellogl_es2/glwidget.cpp index 6b08662..bb07b22 100644 --- a/examples/opengl/hellogl_es2/glwidget.cpp +++ b/examples/opengl/hellogl_es2/glwidget.cpp @@ -41,6 +41,7 @@ #include "glwidget.h" #include +#include #include #include "bubble.h" @@ -265,6 +266,8 @@ void GLWidget::paintGL() QPainter painter; painter.begin(this); + painter.paintEngine()->syncState(); + glClearColor(0.1f, 0.1f, 0.2f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_TEXTURE_2D); diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index edc7c44..f261ca2 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -676,6 +676,11 @@ void QGL2PaintEngineEx::sync() glDisable(GL_BLEND); glActiveTexture(GL_TEXTURE0); + glDisable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + glDepthMask(true); + glClearDepth(1); + d->needsSync = true; } -- cgit v0.12 From e14d27dc775d508dc7300e36ba6a3809eb3f61e4 Mon Sep 17 00:00:00 2001 From: Norwegian Rock Cat Date: Wed, 1 Jul 2009 14:34:21 +0200 Subject: Implement hitTest Cocoa calls hitTest on our view to determine if the view should get the mouse press. We always said, "yes" and did all the logic ourselves. Turns out that we can say "no" if I'm transparent to mouse events and remove all that code where we do all the work ourselves. Big maintenance win! For the time being I've kept the "transparentViewForEvent" method since it might be useful for others, but no one is using it at the moment and we may just kill it soon. HitTest should handle this situation correctly. --- src/gui/kernel/qcocoaview_mac.mm | 17 ++++++------- src/gui/kernel/qt_cocoa_helpers_mac.mm | 44 ---------------------------------- 2 files changed, 7 insertions(+), 54 deletions(-) diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm index 28179b7..64cdae6 100644 --- a/src/gui/kernel/qcocoaview_mac.mm +++ b/src/gui/kernel/qcocoaview_mac.mm @@ -557,6 +557,13 @@ extern "C" { return !qwidget->testAttribute(Qt::WA_MacNoClickThrough); } +- (NSView *)hitTest:(NSPoint)aPoint +{ + if (qwidget->testAttribute(Qt::WA_TransparentForMouseEvents)) + return nil; // You cannot hit a transparent for mouse event widget. + return [super hitTest:aPoint]; +} + - (void)updateTrackingAreas { QMacCocoaAutoReleasePool pool; @@ -793,16 +800,6 @@ extern "C" { Qt::KeyboardModifiers keyMods = qt_cocoaModifiers2QtModifiers([theEvent modifierFlags]); QWidget *widgetToGetMouse = qwidget; - if (widgetToGetMouse->testAttribute(Qt::WA_TransparentForMouseEvents)) { - // Simulate passing the event through since Cocoa doesn't do that for us. - // Start by building a tree up. - NSView *candidateView = [self viewUnderTransparentForMouseView:self - widget:widgetToGetMouse - withWindowPoint:windowPoint]; - if (candidateView != nil) { - widgetToGetMouse = QWidget::find(WId(candidateView)); - } - } // Mouse wheel deltas seem to tick in at increments of 0.1. Qt widgets // expect the delta to be a multiple of 120. diff --git a/src/gui/kernel/qt_cocoa_helpers_mac.mm b/src/gui/kernel/qt_cocoa_helpers_mac.mm index f5f381e..073a00e 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac.mm +++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm @@ -894,50 +894,6 @@ bool qt_mac_handleMouseEvent(void * /* NSView * */view, void * /* NSEvent * */ev NSPoint localPoint = [tmpView convertPoint:windowPoint fromView:nil]; QPoint qlocalPoint(localPoint.x, localPoint.y); - if (widgetToGetMouse->testAttribute(Qt::WA_TransparentForMouseEvents)) { - // Simulate passing the event through since Cocoa doesn't do that for us. - // Start by building a tree up. - NSView *candidateView = [theView viewUnderTransparentForMouseView:tmpView - widget:widgetToGetMouse - withWindowPoint:windowPoint]; - if (candidateView != nil) { - // Fast-track our views, since dispatching trough the normal ways - // would just end up going through here anyway. - if ([candidateView isKindOfClass:[QT_MANGLE_NAMESPACE(QCocoaView) class]]) { - return qt_mac_handleMouseEvent(candidateView, theEvent, eventType, button); - } else { - switch (eventType) { - default: - qWarning("not handled! %d", eventType); - break; - case QEvent::MouseMove: - [candidateView mouseMoved:theEvent]; - break; - case QEvent::MouseButtonPress: - if (button == Qt::LeftButton) - [candidateView mouseDown:theEvent]; - else if (button == Qt::RightButton) - [candidateView rightMouseDown:theEvent]; - else - [candidateView otherMouseDown:theEvent]; - break; - case QEvent::MouseButtonRelease: - if (button == Qt::LeftButton) - [candidateView mouseUp:theEvent]; - else if (button == Qt::RightButton) - [candidateView rightMouseUp:theEvent]; - else - [candidateView otherMouseUp:theEvent]; - break; - } - return true; // We've done the dispatching, no need go further. - } - } - // Nothing below me return false - return false; - } - - EventRef carbonEvent = static_cast(const_cast([theEvent eventRef])); if (qt_mac_sendMacEventToWidget(widgetToGetMouse, carbonEvent)) return true; -- cgit v0.12 From 1d32cdf73843ba98104fdbc6d5d0a296dbb689b0 Mon Sep 17 00:00:00 2001 From: Norwegian Rock Cat Date: Wed, 1 Jul 2009 14:34:43 +0200 Subject: Remove this stale function. --- src/gui/kernel/qapplication_mac.mm | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/src/gui/kernel/qapplication_mac.mm b/src/gui/kernel/qapplication_mac.mm index ce4e422..0884976 100644 --- a/src/gui/kernel/qapplication_mac.mm +++ b/src/gui/kernel/qapplication_mac.mm @@ -1367,29 +1367,6 @@ QWidget *QApplication::topLevelAt(const QPoint &p) #endif } -static QWidget *qt_mac_recursive_widgetAt(QWidget *widget, int x, int y) -{ - if (!widget) - return 0; - const QObjectList kids = widget->children(); - for(int i = kids.size()-1; i >= 0; --i) { - if ( QWidget *kid = qobject_cast(kids.at(i)) ) { - if (kid->isVisible() && !kid->isTopLevel() && - !kid->testAttribute(Qt::WA_TransparentForMouseEvents)) { - const int wx=kid->x(), wy=kid->y(), - wx2=wx+kid->width(), wy2=wy+kid->height(); - if (x >= wx && y >= wy && x < wx2 && y < wy2) { - const QRegion mask = kid->mask(); - if (!mask.isEmpty() && !mask.contains(QPoint(x-wx, y-wy))) - continue; - return qt_mac_recursive_widgetAt(kid, x-wx, y-wy); - } - } - } - } - return widget; -} - /***************************************************************************** Main event loop *****************************************************************************/ -- cgit v0.12 From 7ab895f576b8ef8380838778958fae651a550f79 Mon Sep 17 00:00:00 2001 From: Suneel BS Date: Fri, 8 May 2009 11:09:45 +0530 Subject: Fixed inheritance of some attributes in SVG. Fixed inheritance of stroke attributes, the font-size and text-anchor attribute. Autotest added by Kim. Reviewed-by: Kim --- src/svg/qsvghandler.cpp | 244 +++++++++++++++++---------- src/svg/qsvgnode.cpp | 2 +- src/svg/qsvgstyle.cpp | 8 +- src/svg/qsvgstyle_p.h | 12 +- tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp | 124 ++++++++++++++ 5 files changed, 294 insertions(+), 96 deletions(-) diff --git a/src/svg/qsvghandler.cpp b/src/svg/qsvghandler.cpp index 345dcf3..5950fac 100644 --- a/src/svg/qsvghandler.cpp +++ b/src/svg/qsvghandler.cpp @@ -908,103 +908,155 @@ static void parsePen(QSvgNode *node, //qDebug()<<"Node "<type()<<", attrs are "<(node->styleProperty( - QSvgStyleProperty::STROKE)); - if (!inherited) - inherited = static_cast(node->parent()->styleProperty( - QSvgStyleProperty::STROKE)); - QPen pen(handler->defaultPen()); - if (inherited) - pen = inherited->qpen(); + /* All the below checks needed because g (or any container element) can have only one of these attributes. + * If it doesn't has any one of these, then processing below not needed */ + + if (!value.isEmpty() || !width.isEmpty() || !dashArray.isEmpty() || !linecap.isEmpty() || + !linejoin.isEmpty() || !miterlimit.isEmpty() || !opacity.isEmpty() || !dashOffset.isEmpty() ) { + //if (value != QLatin1String("none")) { + /* If stroke = "none" then also, we need to parse below, because elements like 'g' may + have other defined stroke attributes, which will be inherited by its children */ + QSvgStrokeStyle *inherited = + static_cast(node->parent()->styleProperty( + QSvgStyleProperty::STROKE)); + + QPen pen(handler->defaultPen()); + bool stroke = false; + if (inherited) { + pen = inherited->qpen(); + stroke = inherited->strokePresent(); + } - if (!value.isEmpty()) { - if (value.startsWith(QLatin1String("url"))) { - value = value.remove(0, 3); - QSvgStyleProperty *style = styleFromUrl(node, value); - if (style) { - if (style->type() == QSvgStyleProperty::GRADIENT) { - QBrush b(*((QSvgGradientStyle*)style)->qgradient()); - pen.setBrush(b); - } else if (style->type() == QSvgStyleProperty::SOLID_COLOR) { - pen.setColor( - ((QSvgSolidColorStyle*)style)->qcolor()); - } - } else { - qWarning() << "QSvgHandler::parsePen could not resolve property" << idFromUrl(value); + // stroke-opacity attribute handling + qreal strokeAlpha; + if (!opacity.isEmpty() && opacity != QLatin1String("inherit")) { + strokeAlpha = qMin(qreal(1.0), qMax(qreal(0.0), toDouble(opacity))); + } else { + strokeAlpha = pen.color().alphaF(); + } + + //stroke attribute handling + if (!value.isEmpty() && value != QLatin1String("inherit")) { + if (value.startsWith(QLatin1String("url"))) { + value = value.remove(0, 3); + QSvgStyleProperty *style = styleFromUrl(node, value); + if (style) { + if (style->type() == QSvgStyleProperty::GRADIENT) { + QBrush b(*((QSvgGradientStyle*)style)->qgradient()); + pen.setBrush(b); + } else if (style->type() == QSvgStyleProperty::SOLID_COLOR) { + pen.setColor( + ((QSvgSolidColorStyle*)style)->qcolor()); } + pen.setStyle(Qt::SolidLine); + stroke = true; } else { - QColor color; - if (constructColor(value, opacity, color, handler)) - pen.setColor(color); + qWarning() << "QSvgHandler::parsePen could not resolve property" << idFromUrl(value); } - //since we could inherit stroke="none" - //we need to reset the style of our stroke to something - pen.setStyle(Qt::SolidLine); - } - if (!width.isEmpty()) { - QSvgHandler::LengthType lt; - qreal widthF = parseLength(width, lt, handler); - //### fixme - if (!widthF) { - pen.setStyle(Qt::NoPen); - return; + } else if (value == QLatin1String("none")) { + QColor color; //### fixme: dafalut value for color. + color.setAlphaF(strokeAlpha); + pen.setColor(color); + stroke = false; // This is required because, parent may have a valid stroke but the child may have stroke = "none" + } else { + QColor color; + if (resolveColor(value, color, handler)) { + color.setAlphaF(strokeAlpha); + pen.setColor(color); } - pen.setWidthF(widthF); - } - - if (!linejoin.isEmpty()) { - if (linejoin == QLatin1String("miter")) - pen.setJoinStyle(Qt::SvgMiterJoin); - else if (linejoin == QLatin1String("round")) - pen.setJoinStyle(Qt::RoundJoin); - else if (linejoin == QLatin1String("bevel")) - pen.setJoinStyle(Qt::BevelJoin); + stroke = true; } + } else { + QColor color = pen.color(); + color.setAlphaF(strokeAlpha); + pen.setColor(color); + } - if (!linecap.isEmpty()) { - if (linecap == QLatin1String("butt")) - pen.setCapStyle(Qt::FlatCap); - else if (linecap == QLatin1String("round")) - pen.setCapStyle(Qt::RoundCap); - else if (linecap == QLatin1String("square")) - pen.setCapStyle(Qt::SquareCap); - } + //stroke-width handling + if (!width.isEmpty() && width != QLatin1String("inherit")) { + qreal widthF; + QSvgHandler::LengthType lt; + widthF = parseLength(width, lt, handler); + pen.setWidthF(widthF); + } else if (inherited){ + qreal widthF = inherited->qpen().widthF(); + pen.setWidthF(widthF); + } - qreal penw = pen.widthF(); - if (!dashArray.isEmpty()) { - const QChar *s = dashArray.constData(); - QVector dashes = parseNumbersList(s); - qreal *d = dashes.data(); - if(penw != 0) - for (int i = 0; i < dashes.size(); ++i) { - *d /= penw; - ++d; - } + //stroke-linejoin attribute handling + if (!linejoin.isEmpty()) { + if (linejoin == QLatin1String("miter")) + pen.setJoinStyle(Qt::SvgMiterJoin); + else if (linejoin == QLatin1String("round")) + pen.setJoinStyle(Qt::RoundJoin); + else if (linejoin == QLatin1String("bevel")) + pen.setJoinStyle(Qt::BevelJoin); + } - // if the dash count is odd the dashes should be duplicated - if (dashes.size() % 2 != 0) - dashes << QVector(dashes); + //stroke-linecap attribute handling + if (!linecap.isEmpty()) { + if (linecap == QLatin1String("butt")) + pen.setCapStyle(Qt::FlatCap); + else if (linecap == QLatin1String("round")) + pen.setCapStyle(Qt::RoundCap); + else if (linecap == QLatin1String("square")) + pen.setCapStyle(Qt::SquareCap); + } - pen.setDashPattern(dashes); - } - if (!dashOffset.isEmpty()) { - qreal doffset = toDouble(dashOffset); - if (penw != 0) - doffset /= penw; - pen.setDashOffset(doffset); + //strok-dasharray attribute handling + qreal penw = pen.widthF(); + if (!dashArray.isEmpty() && dashArray != QLatin1String("inherit")) { + const QChar *s = dashArray.constData(); + QVector dashes = parseNumbersList(s); + qreal *d = dashes.data(); + if (penw != 0) + for (int i = 0; i < dashes.size(); ++i) { + *d /= penw; + ++d; + } + // if the dash count is odd the dashes should be duplicated + if (dashes.size() % 2 != 0) + dashes << QVector(dashes); + pen.setDashPattern(dashes); + } else if (inherited) { + QVector dashes(inherited->qpen().dashPattern()); + qreal *d = dashes.data(); + if (!penw) + penw = 1.0; + qreal inheritpenw = inherited->qpen().widthF(); + if (!inheritpenw) + inheritpenw = 1.0; + for ( int i = 0; i < dashes.size(); ++i) { + *d *= (inheritpenw/ penw); + ++d; } - if (!miterlimit.isEmpty()) - pen.setMiterLimit(toDouble(miterlimit)); + pen.setDashPattern(dashes); + } - node->appendStyleProperty(new QSvgStrokeStyle(pen), myId); - } else { - QPen pen(handler->defaultPen()); - pen.setStyle(Qt::NoPen); - node->appendStyleProperty(new QSvgStrokeStyle(pen), myId); + + //stroke-dashoffset attribute handling + if (!dashOffset.isEmpty() && dashOffset != QLatin1String("inherit")) { + qreal doffset = toDouble(dashOffset); + if (penw != 0) + doffset /= penw; + pen.setDashOffset(doffset); + } else if (inherited) { + qreal doffset = pen.dashOffset(); + if (!penw) + penw = 1.0; + qreal inheritpenw = inherited->qpen().widthF(); + if (!inheritpenw) + inheritpenw = 1.0; + doffset *= (inheritpenw/ penw); + pen.setDashOffset(doffset); } + + if (!miterlimit.isEmpty() && miterlimit != QLatin1String("inherit")) + pen.setMiterLimit(toDouble(miterlimit)); + + QSvgStrokeStyle *prop = new QSvgStrokeStyle(pen); + prop->setStroke(stroke); + node->appendStyleProperty(prop, myId); } } @@ -1071,10 +1123,14 @@ static bool parseQFont(const QSvgAttributes &attributes, font.setFamily(family.trimmed()); } if (!size.isEmpty()) { - QSvgHandler::LengthType dummy; // should always be pixel size - fontSize = parseLength(size, dummy, handler); - if (fontSize <= 0) - fontSize = 1; + if (size == QLatin1String("inherit")) { + //inherited already + } else { + QSvgHandler::LengthType dummy; // should always be pixel size + fontSize = parseLength(size, dummy, handler); + if (fontSize <= 0) + fontSize = 1; + } font.setPixelSize(qMax(1, int(fontSize))); } if (!style.isEmpty()) { @@ -1154,9 +1210,13 @@ static void parseFont(QSvgNode *node, font = inherited->qfont(); fontSize = inherited->pointSize(); } - if (parseQFont(attributes, font, fontSize, handler)) { + // group or any container element can have only text-anchor and should + // be processed, because its children can inherit from it. + // So checking for text-anchor before parseQfont() + QString anchor = attributes.value(QLatin1String("text-anchor")).toString(); + if (parseQFont(attributes, font, fontSize, handler) || (!anchor.isEmpty())) { QString myId = someId(attributes); - QString anchor = attributes.value(QLatin1String("text-anchor")).toString(); + //QString anchor = attributes.value(QLatin1String("text-anchor")).toString(); QSvgTinyDocument *doc = node->document(); QSvgFontStyle *fontStyle = 0; QString family = (font.family().isEmpty())?myId:font.family(); @@ -1865,7 +1925,7 @@ static bool parseDefaultTextStyle(QSvgNode *node, if (fontStyle) { font = fontStyle->qfont(); fontSize = fontStyle->pointSize(); - if (anchor.isEmpty()) + if (anchor.isEmpty() || anchor == QLatin1String("inherit")) anchor = fontStyle->textAnchor(); } @@ -3395,7 +3455,7 @@ void QSvgHandler::init() m_style = 0; m_animEnd = 0; m_defaultCoords = LT_PX; - m_defaultPen = QPen(Qt::black, 1, Qt::NoPen, Qt::FlatCap, Qt::SvgMiterJoin); + m_defaultPen = QPen(Qt::black, 1, Qt::SolidLine, Qt::FlatCap, Qt::SvgMiterJoin); m_defaultPen.setMiterLimit(4); parse(); } diff --git a/src/svg/qsvgnode.cpp b/src/svg/qsvgnode.cpp index 75c01a9..ce8b3fa 100644 --- a/src/svg/qsvgnode.cpp +++ b/src/svg/qsvgnode.cpp @@ -320,7 +320,7 @@ qreal QSvgNode::strokeWidth() const { QSvgStrokeStyle *stroke = static_cast( styleProperty(QSvgStyleProperty::STROKE)); - if (!stroke || stroke->qpen().style() == Qt::NoPen) + if (!stroke || !stroke->strokePresent()) return 0; return stroke->qpen().widthF(); } diff --git a/src/svg/qsvgstyle.cpp b/src/svg/qsvgstyle.cpp index fec6231..556201b 100644 --- a/src/svg/qsvgstyle.cpp +++ b/src/svg/qsvgstyle.cpp @@ -195,14 +195,18 @@ void QSvgFontStyle::revert(QPainter *p, QSvgExtraStates &) } QSvgStrokeStyle::QSvgStrokeStyle(const QPen &pen) - : m_stroke(pen) + : m_stroke(pen), m_strokePresent(true) { } void QSvgStrokeStyle::apply(QPainter *p, const QRectF &, QSvgNode *, QSvgExtraStates &) { m_oldStroke = p->pen(); - p->setPen(m_stroke); + if (!m_strokePresent || !m_stroke.widthF() || !m_stroke.color().alphaF()) { + p->setPen(Qt::NoPen); + } else { + p->setPen(m_stroke); + } } void QSvgStrokeStyle::revert(QPainter *p, QSvgExtraStates &) diff --git a/src/svg/qsvgstyle_p.h b/src/svg/qsvgstyle_p.h index e65b6f5..f1d0811 100644 --- a/src/svg/qsvgstyle_p.h +++ b/src/svg/qsvgstyle_p.h @@ -345,6 +345,16 @@ public: virtual void revert(QPainter *p, QSvgExtraStates &states); virtual Type type() const; + void setStroke(bool stroke) + { + m_strokePresent = stroke; + } + + bool strokePresent() const + { + return m_strokePresent; + } + const QPen & qpen() const { return m_stroke; @@ -359,8 +369,8 @@ private: // stroke-opacity v v 'inherit' | // stroke-width v v 'inherit' | QPen m_stroke; - QPen m_oldStroke; + bool m_strokePresent; }; diff --git a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp index f11aff9..7b62eae 100644 --- a/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp +++ b/tests/auto/qsvgrenderer/tst_qsvgrenderer.cpp @@ -80,6 +80,7 @@ private slots: void opacity(); void paths(); void displayMode(); + void strokeInherit(); #ifndef QT_NO_COMPRESS void testGzLoading(); @@ -925,5 +926,128 @@ void tst_QSvgRenderer::displayMode() } } +void tst_QSvgRenderer::strokeInherit() +{ + static const char *svgs[] = { + // Reference. + "" + " " + " " + " " + " " + " " + " " + "", + // stroke + "" + " " + " " + " " + " " + " " + " " + "", + // stroke-width + "" + " " + " " + " " + " " + " " + " " + "", + // stroke-linecap + "" + " " + " " + " " + " " + " " + " " + "", + // stroke-linejoin + "" + " " + " " + " " + " " + " " + " " + "", + // stroke-miterlimit + "" + " " + " " + " " + " " + " " + " " + "", + // stroke-dasharray + "" + " " + " " + " " + " " + " " + " " + "", + // stroke-dashoffset + "" + " " + " " + " " + " " + " " + " " + "", + // stroke-opacity + "" + " " + " " + " " + " " + " " + " " + "" + }; + + const int COUNT = sizeof(svgs) / sizeof(svgs[0]); + QImage images[COUNT]; + QPainter p; + + for (int i = 0; i < COUNT; ++i) { + QByteArray data(svgs[i]); + QSvgRenderer renderer(data); + QVERIFY(renderer.isValid()); + images[i] = QImage(200, 30, QImage::Format_ARGB32_Premultiplied); + images[i].fill(-1); + p.begin(&images[i]); + renderer.render(&p); + p.end(); + if (i != 0) { + QCOMPARE(images[0], images[i]); + } + } +} + QTEST_MAIN(tst_QSvgRenderer) #include "tst_qsvgrenderer.moc" -- cgit v0.12 From 0b3eaca3f40bde96380544f19c9b8874a60bbdeb Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Wed, 1 Jul 2009 15:50:04 +0200 Subject: Make "make docs" in QTDIR work on Windows, independent of configure -debug/release/debug_and_release - build qdoc3 always into tools\qdoc3 rathern than release/debug subdirs - call it from there Reviewed-by: Marius SO --- doc/doc.pri | 11 ++--------- tools/qdoc3/qdoc3.pro | 1 + 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/doc/doc.pri b/doc/doc.pri index a4c77fe..13d481f 100644 --- a/doc/doc.pri +++ b/doc/doc.pri @@ -2,13 +2,6 @@ # Qt documentation build ##################################################################### -win32 { - QT_WINCONFIG = release/ - !CONFIG(release, debug|release) { - QT_WINCONFIG = debug/ - } -} - DOCS_GENERATION_DEFINES = -Dopensourceedition GENERATOR = $$QT_BUILD_TREE/bin/qhelpgenerator @@ -21,9 +14,9 @@ win32:!win32-g++ { } $$unixstyle { - QDOC = cd $$QT_SOURCE_TREE/tools/qdoc3/test && QT_BUILD_TREE=$$QT_BUILD_TREE QT_SOURCE_TREE=$$QT_SOURCE_TREE $$QT_BUILD_TREE/tools/qdoc3/$${QT_WINCONFIG}qdoc3 $$DOCS_GENERATION_DEFINES + QDOC = cd $$QT_SOURCE_TREE/tools/qdoc3/test && QT_BUILD_TREE=$$QT_BUILD_TREE QT_SOURCE_TREE=$$QT_SOURCE_TREE $$QT_BUILD_TREE/tools/qdoc3/qdoc3 $$DOCS_GENERATION_DEFINES } else { - QDOC = cd $$QT_SOURCE_TREE/tools/qdoc3/test && set QT_BUILD_TREE=$$QT_BUILD_TREE&& set QT_SOURCE_TREE=$$QT_SOURCE_TREE&& $$QT_BUILD_TREE/tools/qdoc3/$${QT_WINCONFIG}qdoc3.exe $$DOCS_GENERATION_DEFINES + QDOC = cd $$QT_SOURCE_TREE/tools/qdoc3/test && set QT_BUILD_TREE=$$QT_BUILD_TREE&& set QT_SOURCE_TREE=$$QT_SOURCE_TREE&& $$QT_BUILD_TREE/tools/qdoc3/qdoc3.exe $$DOCS_GENERATION_DEFINES QDOC = $$replace(QDOC, "/", "\\") } macx { diff --git a/tools/qdoc3/qdoc3.pro b/tools/qdoc3/qdoc3.pro index ed27669..6c1cfd2 100644 --- a/tools/qdoc3/qdoc3.pro +++ b/tools/qdoc3/qdoc3.pro @@ -6,6 +6,7 @@ DEFINES += QT_NO_CAST_TO_ASCII QT = core xml CONFIG += console +CONFIG -= debug_and_release_target build_all:!build_pass { CONFIG -= build_all CONFIG += release -- cgit v0.12 From 5b1f4197d380718a15b3aa176f148bd6324bb1cb Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Wed, 1 Jul 2009 12:19:19 +0200 Subject: QNAM: Direct transfer of HTTP buffer to the QNetworkReply buffer Directly put a QRingBuffer from one QRingBuffer to another QRingBuffer. Reviewed-by: Thiago Macieira --- src/corelib/tools/qringbuffer_p.h | 47 +++++++++++++++++++++++- src/network/access/qhttpnetworkreply.cpp | 8 +++- src/network/access/qhttpnetworkreply_p.h | 1 + src/network/access/qnetworkaccesshttpbackend.cpp | 16 ++++---- src/network/access/qnetworkreplyimpl.cpp | 3 +- 5 files changed, 62 insertions(+), 13 deletions(-) diff --git a/src/corelib/tools/qringbuffer_p.h b/src/corelib/tools/qringbuffer_p.h index b8e08ac..f3daca7 100644 --- a/src/corelib/tools/qringbuffer_p.h +++ b/src/corelib/tools/qringbuffer_p.h @@ -301,6 +301,51 @@ public: return read(size()); } + // read an unspecified amount (will read the first buffer) + inline QByteArray read() { + // multiple buffers, just take the first one + if (head == 0 && tailBuffer != 0) { + QByteArray qba = buffers.takeFirst(); + --tailBuffer; + bufferSize -= qba.length(); + return qba; + } + + // one buffer with good value for head. Just take it. + if (head == 0 && tailBuffer == 0) { + QByteArray qba = buffers.takeFirst(); + qba.resize(tail); + buffers << QByteArray(); + bufferSize = 0; + tail = 0; + return qba; + } + + // Bad case: We have to memcpy. + // We can avoid by initializing the QRingBuffer with basicBlockSize of 0 + // and only using this read() function. + QByteArray qba(readPointer(), nextDataBlockSize()); + buffers.takeFirst(); + head = 0; + if (tailBuffer == 0) { + buffers << QByteArray(); + tail = 0; + } else { + --tailBuffer; + } + bufferSize -= qba.length(); + return qba; + } + + // append a new buffer to the end + inline void append(const QByteArray &qba) { + buffers[tailBuffer].resize(tail); + buffers << qba; + ++tailBuffer; + tail = qba.length(); + bufferSize += qba.length(); + } + inline QByteArray peek(int maxLength) const { int bytesToRead = qMin(size(), maxLength); if(maxLength <= 0) @@ -355,7 +400,7 @@ public: private: QList buffers; int head, tail; - int tailBuffer; + int tailBuffer; // always buffers.size() - 1 int basicBlockSize; int bufferSize; }; diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp index 72aec99..483589b 100644 --- a/src/network/access/qhttpnetworkreply.cpp +++ b/src/network/access/qhttpnetworkreply.cpp @@ -185,6 +185,12 @@ QByteArray QHttpNetworkReply::read(qint64 maxSize) return data; } +QByteArray QHttpNetworkReply::readAny() +{ + Q_D(QHttpNetworkReply); + return d->responseData.read(); +} + bool QHttpNetworkReply::isFinished() const { return d_func()->state == QHttpNetworkReplyPrivate::AllDoneState; @@ -196,7 +202,7 @@ QHttpNetworkReplyPrivate::QHttpNetworkReplyPrivate(const QUrl &newUrl) : QHttpNetworkHeaderPrivate(newUrl), state(NothingDoneState), statusCode(100), majorVersion(0), minorVersion(0), bodyLength(0), contentRead(0), totalProgress(0), currentChunkSize(0), currentChunkRead(0), connection(0), initInflate(false), - autoDecompress(false), requestIsPrepared(false) + autoDecompress(false), responseData(0), requestIsPrepared(false) { } diff --git a/src/network/access/qhttpnetworkreply_p.h b/src/network/access/qhttpnetworkreply_p.h index 26e1047..b86cfaa 100644 --- a/src/network/access/qhttpnetworkreply_p.h +++ b/src/network/access/qhttpnetworkreply_p.h @@ -123,6 +123,7 @@ public: qint64 bytesAvailable() const; qint64 bytesAvailableNextBlock() const; QByteArray read(qint64 maxSize = -1); + QByteArray readAny(); bool isFinished() const; diff --git a/src/network/access/qnetworkaccesshttpbackend.cpp b/src/network/access/qnetworkaccesshttpbackend.cpp index 71808d4..db84e58 100644 --- a/src/network/access/qnetworkaccesshttpbackend.cpp +++ b/src/network/access/qnetworkaccesshttpbackend.cpp @@ -649,16 +649,14 @@ void QNetworkAccessHttpBackend::readFromHttp() if (!httpReply) return; - // We implement the download rate control - // Don't read from QHttpNetworkAccess more than QNetworkAccessBackend wants - // One of the two functions above will be called when we can read again + // We read possibly more than nextDownstreamBlockSize(), but + // this is not a critical thing since it is already in the + // memory anyway - qint64 bytesToRead = qBound(0, httpReply->bytesAvailable(), nextDownstreamBlockSize()); - if (!bytesToRead) - return; - - QByteArray data = httpReply->read(bytesToRead); - writeDownstreamData(data); + while (httpReply->bytesAvailable() != 0 && nextDownstreamBlockSize() != 0) { + const QByteArray data = httpReply->readAny(); + writeDownstreamData(data); + } } void QNetworkAccessHttpBackend::replyFinished() diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp index 6eacdf1..de39970 100644 --- a/src/network/access/qnetworkreplyimpl.cpp +++ b/src/network/access/qnetworkreplyimpl.cpp @@ -393,8 +393,7 @@ void QNetworkReplyImplPrivate::appendDownstreamData(const QByteArray &data) if (!q->isOpen()) return; - char *ptr = readBuffer.reserve(data.size()); - memcpy(ptr, data.constData(), data.size()); + readBuffer.append(data); if (cacheEnabled && !cacheSaveDevice) { // save the meta data -- cgit v0.12 From fef6f4469d4c856abdaaefe1d914c120396ff365 Mon Sep 17 00:00:00 2001 From: Kavindra Devi Palaraja Date: Wed, 1 Jul 2009 16:20:52 +0200 Subject: Doc - some minor fixes to the sentences Reviewed-By: TrustMe --- doc/src/tutorials/addressbook.qdoc | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/doc/src/tutorials/addressbook.qdoc b/doc/src/tutorials/addressbook.qdoc index 23dabb3..33832da 100644 --- a/doc/src/tutorials/addressbook.qdoc +++ b/doc/src/tutorials/addressbook.qdoc @@ -818,21 +818,23 @@ \image addressbook-tutorial-part6-screenshot.png - Although browsing and searching for contacts are useful features, our address - book is not really fully ready for use until we can saving existing contacts - and load them again at a later time. - Qt provides a number of classes for \l{Input/Output and Networking}{input and output}, - but we have chosen to use two which are simple to use in combination: QFile and - QDataStream. - - A QFile object represents a file on disk that can be read from and written to. - QFile is a subclass of the more general QIODevice class which represents many - different kinds of devices. - - A QDataStream object is used to serialize binary data so that it can be stored - in a QIODevice and retrieved again later. Reading from a QIODevice and writing - to it is as simple as opening the stream - with the respective device as a - parameter - and reading from or writing to it. + Although browsing and searching for contacts are useful features, our + address book is not ready for use until we can save existing contacts and + load them again at a later time. + + Qt provides a number of classes for \l{Input/Output and Networking} + {input and output}, but we have chosen to use two which are simple to use + in combination: QFile and QDataStream. + + A QFile object represents a file on disk that can be read from and written + to. QFile is a subclass of the more general QIODevice class which + represents many different kinds of devices. + + A QDataStream object is used to serialize binary data so that it can be + stored in a QIODevice and retrieved again later. Reading from a QIODevice + and writing to it is as simple as opening the stream - with the respective + device as a parameter - and reading from or writing to it. + \section1 Defining the AddressBook Class -- cgit v0.12 From f4a95e6d6e4c046ac4857cbd54f9488d3b67ce5a Mon Sep 17 00:00:00 2001 From: Alexis Menard Date: Wed, 1 Jul 2009 17:09:17 +0200 Subject: Fix a regression with extended style option items. We basically passed an unitialized transform to construct the styleoptions for items that use the useExtendedStyleOption flag. We had an auto-test to cover that but for some reason view.show() was removed by me so the auto-test did nothing. oops. Reviewed-by:bnilsen --- src/gui/graphicsview/qgraphicsscene.cpp | 8 ++++---- tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 4 ++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 8fdf651..8a032f4 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -4312,7 +4312,8 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * if (drawItem) { Q_ASSERT(!itemIsFullyTransparent); Q_ASSERT(itemHasContents); - item->d_ptr->initStyleOption(&styleOptionTmp, transform, exposedRegion + ENSURE_TRANSFORM_PTR + item->d_ptr->initStyleOption(&styleOptionTmp, *transformPtr, exposedRegion ? *exposedRegion : QRegion(), exposedRegion == 0); const bool itemClipsToShape = item->d_ptr->flags & QGraphicsItem::ItemClipsToShape; @@ -4320,10 +4321,9 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * if (savePainter) painter->save(); - if (!itemHasChildren || !itemClipsChildrenToShape) { - ENSURE_TRANSFORM_PTR + if (!itemHasChildren || !itemClipsChildrenToShape) painter->setWorldTransform(*transformPtr); - } + if (itemClipsToShape) painter->setClipPath(item->shape(), Qt::IntersectClip); painter->setOpacity(opacity); diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index 7552f18..3f7a50b 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -6837,9 +6837,11 @@ public: //Doesn't use the extended style option so the exposed rect is the boundingRect if (!(flags() & QGraphicsItem::ItemUsesExtendedStyleOption)) { QCOMPARE(option->exposedRect, boundingRect()); + QCOMPARE(option->matrix, QMatrix()); } else { QVERIFY(option->exposedRect != QRect()); QVERIFY(option->exposedRect != boundingRect()); + QCOMPARE(option->matrix, sceneTransform().toAffine()); } } QGraphicsRectItem::paint(painter, option, widget); @@ -6861,6 +6863,8 @@ void tst_QGraphicsItem::itemUsesExtendedStyleOption() scene.addItem(rect); rect->setPos(200, 200); QGraphicsView view(&scene); + rect->startTrack = false; + view.show(); QTest::qWait(500); rect->startTrack = true; rect->update(10, 10, 10, 10); -- cgit v0.12 From d0299745e511640df3e0a26e8c447d0960ac4546 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Wed, 1 Jul 2009 12:14:29 +0200 Subject: QMainWindow: cleanup of code in QWidgetAnimator --- src/gui/widgets/qdockarealayout.cpp | 10 ++--- src/gui/widgets/qmainwindowlayout.cpp | 50 +++++++-------------- src/gui/widgets/qmainwindowlayout_p.h | 11 ++--- src/gui/widgets/qtoolbararealayout.cpp | 2 +- src/gui/widgets/qwidgetanimator.cpp | 79 +++++++++++++--------------------- src/gui/widgets/qwidgetanimator_p.h | 21 ++++----- 6 files changed, 66 insertions(+), 107 deletions(-) diff --git a/src/gui/widgets/qdockarealayout.cpp b/src/gui/widgets/qdockarealayout.cpp index f245d64..b905ccd 100644 --- a/src/gui/widgets/qdockarealayout.cpp +++ b/src/gui/widgets/qdockarealayout.cpp @@ -1488,7 +1488,7 @@ bool QDockAreaLayoutInfo::hasFixedSize() const void QDockAreaLayoutInfo::apply(bool animate) { - QWidgetAnimator *widgetAnimator = mainWindowLayout()->widgetAnimator; + QWidgetAnimator &widgetAnimator = mainWindowLayout()->widgetAnimator; #ifndef QT_NO_TABBAR if (tabbed) { @@ -1521,7 +1521,7 @@ void QDockAreaLayoutInfo::apply(bool animate) } } - widgetAnimator->animate(tabBar, tab_rect, animate); + widgetAnimator.animate(tabBar, tab_rect, animate); } #endif // QT_NO_TABBAR @@ -1544,7 +1544,7 @@ void QDockAreaLayoutInfo::apply(bool animate) QWidget *w = item.widgetItem->widget(); QRect geo = w->geometry(); - widgetAnimator->animate(w, r, animate); + widgetAnimator.animate(w, r, animate); if (!w->isHidden()) { QDockWidget *dw = qobject_cast(w); if (!r.isValid() && geo.right() >= 0 && geo.bottom() >= 0) { @@ -3064,13 +3064,13 @@ void QDockAreaLayout::splitDockWidget(QDockWidget *after, void QDockAreaLayout::apply(bool animate) { - QWidgetAnimator *widgetAnimator + QWidgetAnimator &widgetAnimator = qobject_cast(mainWindow->layout())->widgetAnimator; for (int i = 0; i < QInternal::DockCount; ++i) docks[i].apply(animate); if (centralWidgetItem != 0 && !centralWidgetItem->isEmpty()) { - widgetAnimator->animate(centralWidgetItem->widget(), centralWidgetRect, + widgetAnimator.animate(centralWidgetItem->widget(), centralWidgetRect, animate); } diff --git a/src/gui/widgets/qmainwindowlayout.cpp b/src/gui/widgets/qmainwindowlayout.cpp index 526e7a5..0318f53 100644 --- a/src/gui/widgets/qmainwindowlayout.cpp +++ b/src/gui/widgets/qmainwindowlayout.cpp @@ -1361,7 +1361,7 @@ QLayoutItem *QMainWindowLayout::takeAt(int index) if (QLayoutItem *ret = layoutState.takeAt(index, &x)) { // the widget might in fact have been destroyed by now if (QWidget *w = ret->widget()) { - widgetAnimator->abort(w); + widgetAnimator.abort(w); if (w == pluggingWidget) pluggingWidget = 0; } @@ -1542,25 +1542,9 @@ bool QMainWindowLayout::plug(QLayoutItem *widgetItem) } } #endif - widgetAnimator->animate(widget, globalRect, - dockOptions & QMainWindow::AnimatedDocks); + widgetAnimator.animate(widget, globalRect, true); } else { -#ifndef QT_NO_DOCKWIDGET - if (QDockWidget *dw = qobject_cast(widget)) - dw->d_func()->plug(currentGapRect); -#endif -#ifndef QT_NO_TOOLBAR - if (QToolBar *tb = qobject_cast(widget)) - tb->d_func()->plug(currentGapRect); -#endif - applyState(layoutState); - savedState.clear(); -#ifndef QT_NO_DOCKWIDGET - parentWidget()->update(layoutState.dockAreaLayout.separatorRegion()); -#endif - currentGapPos.clear(); - updateGapIndicator(); - pluggingWidget = 0; + animationFinished(widget); } return true; @@ -1667,6 +1651,11 @@ QMainWindowLayout::QMainWindowLayout(QMainWindow *mainwindow) #endif #endif #endif // QT_NO_DOCKWIDGET + , widgetAnimator(this) + , pluggingWidget(0) +#ifndef QT_NO_RUBBERBAND + , gapIndicator(QRubberBand::Rectangle, mainwindow) +#endif //QT_NO_RUBBERBAND { #ifndef QT_NO_DOCKWIDGET #ifndef QT_NO_TABBAR @@ -1680,20 +1669,13 @@ QMainWindowLayout::QMainWindowLayout(QMainWindow *mainwindow) #endif // QT_NO_DOCKWIDGET #ifndef QT_NO_RUBBERBAND - gapIndicator = new QRubberBand(QRubberBand::Rectangle, mainwindow); // For accessibility to identify this special widget. - gapIndicator->setObjectName(QLatin1String("qt_rubberband")); - - gapIndicator->hide(); + gapIndicator.setObjectName(QLatin1String("qt_rubberband")); + gapIndicator.hide(); #endif pluggingWidget = 0; setObjectName(mainwindow->objectName() + QLatin1String("_layout")); - widgetAnimator = new QWidgetAnimator(this); - connect(widgetAnimator, SIGNAL(finished(QWidget*)), - this, SLOT(animationFinished(QWidget*)), Qt::QueuedConnection); - connect(widgetAnimator, SIGNAL(finishedAll()), - this, SLOT(allAnimationsFinished())); } QMainWindowLayout::~QMainWindowLayout() @@ -1795,13 +1777,13 @@ QLayoutItem *QMainWindowLayout::unplug(QWidget *widget) void QMainWindowLayout::updateGapIndicator() { #ifndef QT_NO_RUBBERBAND - if (widgetAnimator->animating() || currentGapPos.isEmpty()) { - gapIndicator->hide(); + if (widgetAnimator.animating() || currentGapPos.isEmpty()) { + gapIndicator.hide(); } else { - if (gapIndicator->geometry() != currentGapRect) - gapIndicator->setGeometry(currentGapRect); - if (!gapIndicator->isVisible()) - gapIndicator->show(); + if (gapIndicator.geometry() != currentGapRect) + gapIndicator.setGeometry(currentGapRect); + if (!gapIndicator.isVisible()) + gapIndicator.show(); } #endif } diff --git a/src/gui/widgets/qmainwindowlayout_p.h b/src/gui/widgets/qmainwindowlayout_p.h index 26f8633..5c5965a 100644 --- a/src/gui/widgets/qmainwindowlayout_p.h +++ b/src/gui/widgets/qmainwindowlayout_p.h @@ -59,10 +59,12 @@ #include "QtGui/qlayout.h" #include "QtGui/qtabbar.h" +#include "QtGui/qrubberband.h" #include "QtCore/qvector.h" #include "QtCore/qset.h" #include "QtCore/qbasictimer.h" #include "private/qlayoutengine_p.h" +#include "private/qwidgetanimator_p.h" #include "qdockarealayout_p.h" #include "qtoolbararealayout_p.h" @@ -89,7 +91,6 @@ typedef const struct __CFString * CFStringRef; QT_BEGIN_NAMESPACE class QToolBar; -class QWidgetAnimator; class QRubberBand; /* This data structure represents the state of all the tool-bars and dock-widgets. It's value based @@ -278,12 +279,12 @@ public: // animations - QWidgetAnimator *widgetAnimator; + QWidgetAnimator widgetAnimator; QList currentGapPos; QRect currentGapRect; QWidget *pluggingWidget; #ifndef QT_NO_RUBBERBAND - QRubberBand *gapIndicator; + QRubberBand gapIndicator; #endif QList hover(QLayoutItem *widgetItem, const QPoint &mousePos); @@ -295,10 +296,10 @@ public: void applyState(QMainWindowLayoutState &newState, bool animate = true); void restore(bool keepSavedState = false); void updateHIToolBarStatus(); - -private slots: void animationFinished(QWidget *widget); void allAnimationsFinished(); + +private slots: #ifndef QT_NO_DOCKWIDGET #ifndef QT_NO_TABBAR void tabChanged(); diff --git a/src/gui/widgets/qtoolbararealayout.cpp b/src/gui/widgets/qtoolbararealayout.cpp index db2afd6..0c11700 100644 --- a/src/gui/widgets/qtoolbararealayout.cpp +++ b/src/gui/widgets/qtoolbararealayout.cpp @@ -932,7 +932,7 @@ void QToolBarAreaLayout::apply(bool animate) if (visible && dock.o == Qt::Horizontal) geo = QStyle::visualRect(dir, line.rect, geo); - layout->widgetAnimator->animate(widget, geo, animate); + layout->widgetAnimator.animate(widget, geo, animate); } } } diff --git a/src/gui/widgets/qwidgetanimator.cpp b/src/gui/widgets/qwidgetanimator.cpp index c67be4a..56b3f43 100644 --- a/src/gui/widgets/qwidgetanimator.cpp +++ b/src/gui/widgets/qwidgetanimator.cpp @@ -39,12 +39,8 @@ ** ****************************************************************************/ -#include -#include #include -#include -#include -#include +#include #include "qwidgetanimator_p.h" @@ -75,18 +71,12 @@ static inline int animateHelper(int start, int stop, int step, int steps) return start + g_animate_function[x]*(stop - start)/1000; } -QWidgetAnimator::QWidgetAnimator(QObject *parent) - : QObject(parent) +QWidgetAnimator::QWidgetAnimator(QMainWindowLayout *layout) : m_mainWindowLayout(layout) { - m_time = new QTime(); - m_timer = new QTimer(this); - m_timer->setInterval(g_animation_interval); - connect(m_timer, SIGNAL(timeout()), this, SLOT(animationStep())); } QWidgetAnimator::~QWidgetAnimator() { - delete m_time; } void QWidgetAnimator::abort(QWidget *w) @@ -94,8 +84,8 @@ void QWidgetAnimator::abort(QWidget *w) if (m_animation_map.remove(w) == 0) return; if (m_animation_map.isEmpty()) { - m_timer->stop(); - emit finishedAll(); + m_timer.stop(); + m_mainWindowLayout->allAnimationsFinished(); } } @@ -107,32 +97,21 @@ void QWidgetAnimator::animate(QWidget *widget, const QRect &_final_geometry, boo if (r.right() < 0 || r.bottom() < 0) r = QRect(); - if (r.isNull() || final_geometry.isNull()) + if (r.isNull() || final_geometry.isNull() || r == final_geometry) animate = false; AnimationMap::const_iterator it = m_animation_map.constFind(widget); - if (it == m_animation_map.constEnd()) { - if (r == final_geometry) { - emit finished(widget); - return; - } - } else { - if ((*it).r2 == final_geometry) - return; - } + if (it != m_animation_map.constEnd() && (*it).r2 == final_geometry) + return; if (animate) { AnimationItem item(widget, r, final_geometry); m_animation_map[widget] = item; - if (!m_timer->isActive()) { - m_timer->start(); - m_time->start(); + if (!m_timer.isActive()) { + m_timer.start(g_animation_interval, this); + m_time.start(); } } else { - m_animation_map.remove(widget); - if (m_animation_map.isEmpty()) - m_timer->stop(); - if (!final_geometry.isValid() && !widget->isWindow()) { // Make the wigdet go away by sending it to negative space QSize s = widget->size(); @@ -140,18 +119,19 @@ void QWidgetAnimator::animate(QWidget *widget, const QRect &_final_geometry, boo } widget->setGeometry(final_geometry); - emit finished(widget); - - if (m_animation_map.isEmpty()) - emit finishedAll(); - - return; + if (m_animation_map.remove(widget)) { + m_mainWindowLayout->animationFinished(widget); + if (m_animation_map.isEmpty()) { + m_timer.stop(); + m_mainWindowLayout->allAnimationsFinished(); + } + } } } -void QWidgetAnimator::animationStep() +void QWidgetAnimator::timerEvent(QTimerEvent *) { - int steps = (1 + m_time->restart())/g_animation_interval; + int steps = (1 + m_time.restart())/g_animation_interval; AnimationMap::iterator it = m_animation_map.begin(); while (it != m_animation_map.end()) { AnimationItem &item = *it; @@ -159,35 +139,34 @@ void QWidgetAnimator::animationStep() item.step = qMin(item.step + steps, g_animation_steps); int x = animateHelper(item.r1.left(), item.r2.left(), - item.step, g_animation_steps); + item.step, g_animation_steps); int y = animateHelper(item.r1.top(), item.r2.top(), - item.step, g_animation_steps); + item.step, g_animation_steps); int w = animateHelper(item.r1.width(), item.r2.width(), - item.step, g_animation_steps); + item.step, g_animation_steps); int h = animateHelper(item.r1.height(), item.r2.height(), - item.step, g_animation_steps); + item.step, g_animation_steps); item.widget->setGeometry(x, y, w, h); if (item.step == g_animation_steps) { - emit finished(item.widget); - AnimationMap::iterator tmp = it; - ++it; - m_animation_map.erase(tmp); + QWidget *widget = item.widget; + it = m_animation_map.erase(it); + m_mainWindowLayout->animationFinished(widget); } else { ++it; } } if (m_animation_map.isEmpty()) { - m_timer->stop(); - emit finishedAll(); + m_timer.stop(); + m_mainWindowLayout->allAnimationsFinished(); } } bool QWidgetAnimator::animating() const { - return m_timer->isActive(); + return m_timer.isActive(); } bool QWidgetAnimator::animating(QWidget *widget) diff --git a/src/gui/widgets/qwidgetanimator_p.h b/src/gui/widgets/qwidgetanimator_p.h index 6ee150b..0c68e00 100644 --- a/src/gui/widgets/qwidgetanimator_p.h +++ b/src/gui/widgets/qwidgetanimator_p.h @@ -56,18 +56,18 @@ #include #include #include +#include +#include QT_BEGIN_NAMESPACE class QWidget; -class QTimer; -class QTime; +class QMainWindowLayout; class QWidgetAnimator : public QObject { - Q_OBJECT public: - QWidgetAnimator(QObject *parent = 0); + QWidgetAnimator(QMainWindowLayout *layout); ~QWidgetAnimator(); void animate(QWidget *widget, const QRect &final_geometry, bool animate); bool animating() const; @@ -75,12 +75,8 @@ public: void abort(QWidget *widget); -signals: - void finished(QWidget *widget); - void finishedAll(); - -private slots: - void animationStep(); +protected: + void timerEvent(QTimerEvent *e); private: struct AnimationItem { @@ -93,8 +89,9 @@ private: }; typedef QMap AnimationMap; AnimationMap m_animation_map; - QTimer *m_timer; - QTime *m_time; + QBasicTimer m_timer; + QTime m_time; + QMainWindowLayout *m_mainWindowLayout; }; QT_END_NAMESPACE -- cgit v0.12 From 5077f0be81128ee81e8c7875eb9d1e9423868808 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Wed, 1 Jul 2009 15:54:10 +0200 Subject: Animation: fixed a NOTIFY signal name that was wrong Also slightly updated a demo --- examples/animation/animatedtiles/main.cpp | 12 ++++++------ src/corelib/animation/qvariantanimation.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/animation/animatedtiles/main.cpp b/examples/animation/animatedtiles/main.cpp index 9360d7c..c0d55f3 100644 --- a/examples/animation/animatedtiles/main.cpp +++ b/examples/animation/animatedtiles/main.cpp @@ -178,7 +178,7 @@ int main(int argc, char **argv) QState *centeredState = new QState(rootState); // Values - for (int i = 0; i < 64; ++i) { + for (int i = 0; i < items.count(); ++i) { Pixmap *item = items.at(i); // Ellipse ellipseState->assignProperty(item, "pos", @@ -219,7 +219,7 @@ int main(int argc, char **argv) rootState->setInitialState(centeredState); QParallelAnimationGroup *group = new QParallelAnimationGroup; - for (int i = 0; i < 64; ++i) { + for (int i = 0; i < items.count(); ++i) { QPropertyAnimation *anim = new QPropertyAnimation(items[i], "pos"); anim->setDuration(750 + i * 25); anim->setEasingCurve(QEasingCurve::InOutBack); @@ -229,7 +229,7 @@ int main(int argc, char **argv) trans->addAnimation(group); group = new QParallelAnimationGroup; - for (int i = 0; i < 64; ++i) { + for (int i = 0; i < items.count(); ++i) { QPropertyAnimation *anim = new QPropertyAnimation(items[i], "pos"); anim->setDuration(750 + i * 25); anim->setEasingCurve(QEasingCurve::InOutBack); @@ -239,7 +239,7 @@ int main(int argc, char **argv) trans->addAnimation(group); group = new QParallelAnimationGroup; - for (int i = 0; i < 64; ++i) { + for (int i = 0; i < items.count(); ++i) { QPropertyAnimation *anim = new QPropertyAnimation(items[i], "pos"); anim->setDuration(750 + i * 25); anim->setEasingCurve(QEasingCurve::InOutBack); @@ -249,7 +249,7 @@ int main(int argc, char **argv) trans->addAnimation(group); group = new QParallelAnimationGroup; - for (int i = 0; i < 64; ++i) { + for (int i = 0; i < items.count(); ++i) { QPropertyAnimation *anim = new QPropertyAnimation(items[i], "pos"); anim->setDuration(750 + i * 25); anim->setEasingCurve(QEasingCurve::InOutBack); @@ -259,7 +259,7 @@ int main(int argc, char **argv) trans->addAnimation(group); group = new QParallelAnimationGroup; - for (int i = 0; i < 64; ++i) { + for (int i = 0; i < items.count(); ++i) { QPropertyAnimation *anim = new QPropertyAnimation(items[i], "pos"); anim->setDuration(750 + i * 25); anim->setEasingCurve(QEasingCurve::InOutBack); diff --git a/src/corelib/animation/qvariantanimation.h b/src/corelib/animation/qvariantanimation.h index b2d52d5..3e397ca 100644 --- a/src/corelib/animation/qvariantanimation.h +++ b/src/corelib/animation/qvariantanimation.h @@ -62,7 +62,7 @@ class Q_CORE_EXPORT QVariantAnimation : public QAbstractAnimation Q_OBJECT Q_PROPERTY(QVariant startValue READ startValue WRITE setStartValue) Q_PROPERTY(QVariant endValue READ endValue WRITE setEndValue) - Q_PROPERTY(QVariant currentValue READ currentValue NOTIFY currentValueChanged) + Q_PROPERTY(QVariant currentValue READ currentValue NOTIFY valueChanged) Q_PROPERTY(int duration READ duration WRITE setDuration) Q_PROPERTY(QEasingCurve easingCurve READ easingCurve WRITE setEasingCurve) -- cgit v0.12 From 0ee90990c24bf965317918074a5af683e94bdd40 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Wed, 1 Jul 2009 16:38:37 +0200 Subject: Animations: adding an autotest for jumping values when restarting The problem is that when restarting, the time is at the end. So the current value changes to the end value instead of the initial value. --- .../qpropertyanimation/tst_qpropertyanimation.cpp | 52 ++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/tests/auto/qpropertyanimation/tst_qpropertyanimation.cpp b/tests/auto/qpropertyanimation/tst_qpropertyanimation.cpp index a30e9f9..09e12c3 100644 --- a/tests/auto/qpropertyanimation/tst_qpropertyanimation.cpp +++ b/tests/auto/qpropertyanimation/tst_qpropertyanimation.cpp @@ -111,6 +111,7 @@ private slots: void operationsInStates(); void oneKeyValue(); void updateOnSetKeyValues(); + void restart(); }; tst_QPropertyAnimation::tst_QPropertyAnimation() @@ -559,6 +560,9 @@ void tst_QPropertyAnimation::startWithoutStartValue() QTest::qWait(200); QCOMPARE(anim.state(), QVariantAnimation::Stopped); + current = anim.currentValue().toInt(); + QCOMPARE(current, 100); + QCOMPARE(o.property("ole").toInt(), current); anim.setEndValue(110); anim.start(); @@ -954,5 +958,53 @@ void tst_QPropertyAnimation::updateOnSetKeyValues() QCOMPARE(animation2.currentValue().toInt(), animation.currentValue().toInt()); } + +//this class will 'throw' an error in the test lib +// if the property ole is set to ErrorValue +class MyErrorObject : public QObject +{ + Q_OBJECT + Q_PROPERTY(int ole READ ole WRITE setOle) +public: + + static const int ErrorValue = 10000; + + MyErrorObject() : m_ole(0) { } + int ole() const { return m_ole; } + void setOle(int o) + { + QVERIFY(o != ErrorValue); + m_ole = o; + } + +private: + int m_ole; + + +}; + +void tst_QPropertyAnimation::restart() +{ + //here we check that be restarting an animation + //it doesn't get an bogus intermediate value (end value) + //because the time is not yet reset to 0 + MyErrorObject o; + o.setOle(100); + QCOMPARE(o.property("ole").toInt(), 100); + + QPropertyAnimation anim(&o, "ole"); + anim.setEndValue(200); + anim.start(); + anim.setCurrentTime(anim.duration()); + QCOMPARE(anim.state(), QAbstractAnimation::Stopped); + QCOMPARE(o.property("ole").toInt(), 200); + + //we'll check that the animation never gets a wrong value when starting it + //after having changed the end value + anim.setEndValue(MyErrorObject::ErrorValue); + anim.start(); +} + + QTEST_MAIN(tst_QPropertyAnimation) #include "tst_qpropertyanimation.moc" -- cgit v0.12 From 29b71240d17a1557fd9a8d2ce7dcd450b07b57a8 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Wed, 1 Jul 2009 17:15:17 +0200 Subject: QAnimation: fix a jump in values when restarting an animation --- src/corelib/animation/qabstractanimation.cpp | 47 ++++++++++------------ .../qpropertyanimation/tst_qpropertyanimation.cpp | 5 +++ 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp index 3720984..75decf8 100644 --- a/src/corelib/animation/qabstractanimation.cpp +++ b/src/corelib/animation/qabstractanimation.cpp @@ -254,8 +254,17 @@ void QAbstractAnimationPrivate::setState(QAbstractAnimation::State newState) int oldCurrentLoop = currentLoop; QAbstractAnimation::Direction oldDirection = direction; - state = newState; + // check if we should Rewind + if ((newState == QAbstractAnimation::Paused || newState == QAbstractAnimation::Running) + && oldState == QAbstractAnimation::Stopped) { + //here we reset the time if needed + //we don't call setCurrentTime because this might change the way the animation + //behaves: changing the state or changing the current value + totalCurrentTime = currentTime =(direction == QAbstractAnimation::Forward) ? + 0 : (loopCount == -1 ? q->duration() : q->totalDuration()); + } + state = newState; QPointer guard(q); guard->updateState(oldState, newState); @@ -268,36 +277,22 @@ void QAbstractAnimationPrivate::setState(QAbstractAnimation::State newState) if (guard) emit guard->stateChanged(oldState, newState); - // Enter running state. switch (state) { case QAbstractAnimation::Paused: case QAbstractAnimation::Running: - { - // Rewind - if (oldState == QAbstractAnimation::Stopped) { - if (guard) { - if (direction == QAbstractAnimation::Forward) - q->setCurrentTime(0); - else - q->setCurrentTime(loopCount == -1 ? q->duration() : q->totalDuration()); - } - - // Check if the setCurrentTime() function called stop(). - // This can happen for a 0-duration animation - if (state == QAbstractAnimation::Stopped) - return; - } - - // Register timer if our parent is not running. - if (state == QAbstractAnimation::Running && guard) { - if (!group || group->state() == QAbstractAnimation::Stopped) { - QUnifiedTimer::instance()->registerAnimation(q); - } - } else { - //new state is paused - QUnifiedTimer::instance()->unregisterAnimation(q); + //this ensures that the value is updated now that the animation is running + if(oldState == QAbstractAnimation::Stopped && guard) + guard->setCurrentTime(currentTime); + + // Register timer if our parent is not running. + if (state == QAbstractAnimation::Running && guard) { + if (!group || group->state() == QAbstractAnimation::Stopped) { + QUnifiedTimer::instance()->registerAnimation(q); } + } else { + //new state is paused + QUnifiedTimer::instance()->unregisterAnimation(q); } break; case QAbstractAnimation::Stopped: diff --git a/tests/auto/qpropertyanimation/tst_qpropertyanimation.cpp b/tests/auto/qpropertyanimation/tst_qpropertyanimation.cpp index 09e12c3..e76c8ef 100644 --- a/tests/auto/qpropertyanimation/tst_qpropertyanimation.cpp +++ b/tests/auto/qpropertyanimation/tst_qpropertyanimation.cpp @@ -396,8 +396,13 @@ void tst_QPropertyAnimation::duration0() animation.setEndValue(43); QVERIFY(!animation.currentValue().isValid()); QCOMPARE(animation.currentValue().toInt(), 0); + animation.setStartValue(42); + QVERIFY(animation.currentValue().isValid()); + QCOMPARE(animation.currentValue().toInt(), 42); + QCOMPARE(o.property("ole").toInt(), 42); animation.setDuration(0); + QCOMPARE(animation.currentValue().toInt(), 43); //it is at the end animation.start(); QCOMPARE(animation.state(), QAnimationGroup::Stopped); QCOMPARE(animation.currentTime(), 0); -- cgit v0.12 From 2b9294a2b47c4a193ef83be60a07a3e61b8531b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 1 Jul 2009 17:30:46 +0200 Subject: Fixes broken BSP lookup in QGraphicsSceneBspTreeIndex. The chip demo was unbelievable slow, so I investigated and found out the bsp always returned almost all items in the tree (40 000 in this particular case). It did so because the tree was initialized with an empty sceneRect. The sceneRect was empty due to a lacking signal-slot connection, resulting in QGraphicsSceneBspTreeIndex::updateSceneRect never being invoked. Auto-test included. --- src/gui/graphicsview/qgraphicssceneindex.cpp | 17 ++++++++++++----- src/gui/graphicsview/qgraphicssceneindex_p.h | 3 ++- .../qgraphicssceneindex/tst_qgraphicssceneindex.cpp | 13 +++++++++++++ 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index 2f2f05e..b317e8e 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -303,24 +303,31 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRe } } +void QGraphicsSceneIndexPrivate::init() +{ + if (!scene) + return; + + QObject::connect(scene, SIGNAL(sceneRectChanged(const QRectF&)), + q_func(), SLOT(updateSceneRect(const QRectF&))); +} + /*! Constructs an abstract scene index for a given \a scene. */ QGraphicsSceneIndex::QGraphicsSceneIndex(QGraphicsScene *scene) : QObject(*new QGraphicsSceneIndexPrivate(scene), scene) { - if (scene) { - connect(scene, SIGNAL(sceneRectChanged(const QRectF&)), - this, SLOT(updateSceneRect(const QRectF&))); - } + d_func()->init(); } /*! \internal */ -QGraphicsSceneIndex::QGraphicsSceneIndex(QObjectPrivate &dd, QGraphicsScene *scene) +QGraphicsSceneIndex::QGraphicsSceneIndex(QGraphicsSceneIndexPrivate &dd, QGraphicsScene *scene) : QObject(dd, scene) { + d_func()->init(); } /*! diff --git a/src/gui/graphicsview/qgraphicssceneindex_p.h b/src/gui/graphicsview/qgraphicssceneindex_p.h index 122d7ae..aabfa79 100644 --- a/src/gui/graphicsview/qgraphicssceneindex_p.h +++ b/src/gui/graphicsview/qgraphicssceneindex_p.h @@ -114,7 +114,7 @@ protected: virtual void itemChange(const QGraphicsItem *item, QGraphicsItem::GraphicsItemChange, const QVariant &value); virtual void prepareBoundingRectChange(const QGraphicsItem *item); - QGraphicsSceneIndex(QObjectPrivate &dd, QGraphicsScene *scene); + QGraphicsSceneIndex(QGraphicsSceneIndexPrivate &dd, QGraphicsScene *scene); friend class QGraphicsScene; friend class QGraphicsScenePrivate; @@ -133,6 +133,7 @@ public: QGraphicsSceneIndexPrivate(QGraphicsScene *scene); ~QGraphicsSceneIndexPrivate(); + void init(); static bool itemCollidesWithPath(const QGraphicsItem *item, const QPainterPath &path, Qt::ItemSelectionMode mode); void recursive_items_helper(QGraphicsItem *item, QRectF exposeRect, diff --git a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp index ac21e20..9d0675d 100644 --- a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp +++ b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp @@ -64,6 +64,7 @@ private slots: void overlappedItems(); void movingItems_data(); void movingItems(); + void connectedToSceneRectChanged(); private: void common_data(); @@ -214,6 +215,18 @@ void tst_QGraphicsSceneIndex::movingItems() QCOMPARE(scene.items(QRectF(0, 0, 1000, 1000)).count(), 11); } +void tst_QGraphicsSceneIndex::connectedToSceneRectChanged() +{ + + class MyScene : public QGraphicsScene + { public: using QGraphicsScene::receivers; }; + + MyScene scene; // Uses QGraphicsSceneBspTreeIndex by default. + QCOMPARE(scene.receivers(SIGNAL(sceneRectChanged(const QRectF&))), 1); + + scene.setItemIndexMethod(QGraphicsScene::NoIndex); // QGraphicsSceneLinearIndex + QCOMPARE(scene.receivers(SIGNAL(sceneRectChanged(const QRectF&))), 1); +} QTEST_MAIN(tst_QGraphicsSceneIndex) #include "tst_qgraphicssceneindex.moc" -- cgit v0.12 From f31d2c01e5998a9fcf4345fa66e0349921e115da Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Thu, 2 Jul 2009 09:57:52 +1000 Subject: OpenVG: use the correct clip region to detect single-rect clips "Special case: if the intersection of the system clip and the region is a single rectangle, then use the scissor for clipping." It was doing the intersection but then didn't use the intersection to test for the single-rectangle case. Task-number: QT-64 Reviewed-by: trustme --- src/openvg/qpaintengine_vg.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp index c7fe604..8ce3f69 100644 --- a/src/openvg/qpaintengine_vg.cpp +++ b/src/openvg/qpaintengine_vg.cpp @@ -1656,10 +1656,10 @@ void QVGPaintEngine::clip(const QRegion ®ion, Qt::ClipOperation op) clip = r; else clip = clip.intersect(r); - if (r.numRects() == 1) { + if (clip.numRects() == 1) { d->maskValid = false; d->maskIsSet = false; - d->maskRect = r.boundingRect(); + d->maskRect = clip.boundingRect(); vgSeti(VG_MASKING, VG_FALSE); updateScissor(); } else { -- cgit v0.12 From 0b5c4c4352d0419113cf152b7ae5bbee5a45fd5c Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Thu, 2 Jul 2009 10:36:19 +1000 Subject: OpenVG: override QPaintEngineEx::clip(QRect) and handle specially. This change should improve performance of single-rectangle clip regions by avoiding the overhead of creating and intersecting QRegion objects. Task-number: QT-64 Reviewed-by: trustme --- src/openvg/qpaintengine_vg.cpp | 130 ++++++++++++++++++++++++++++++++++++++++- src/openvg/qpaintengine_vg_p.h | 1 + 2 files changed, 129 insertions(+), 2 deletions(-) diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp index 8ce3f69..48953ac 100644 --- a/src/openvg/qpaintengine_vg.cpp +++ b/src/openvg/qpaintengine_vg.cpp @@ -142,6 +142,8 @@ public: void ensureMask(QVGPaintEngine *engine, int width, int height); void modifyMask (QVGPaintEngine *engine, VGMaskOperation op, const QRegion& region); + void modifyMask + (QVGPaintEngine *engine, VGMaskOperation op, const QRect& rect); #endif VGint maxScissorRects; // Maximum scissor rectangles for clipping. @@ -1611,13 +1613,106 @@ void QVGPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op) void QVGPaintEngine::clip(const QRect &rect, Qt::ClipOperation op) { - clip(QRegion(rect), op); + Q_D(QVGPaintEngine); + + d->dirty |= QPaintEngine::DirtyClipRegion; + + // If we have a non-simple transform, then use path-based clipping. + if (op != Qt::NoClip && !clipTransformIsSimple(d->transform)) { + QPaintEngineEx::clip(rect, op); + return; + } + + switch (op) { + case Qt::NoClip: + { + d->maskValid = false; + d->maskIsSet = true; + d->maskRect = QRect(); + vgSeti(VG_MASKING, VG_FALSE); + } + break; + + case Qt::ReplaceClip: + { + QRect r = d->transform.mapRect(rect); + if (isDefaultClipRect(r)) { + // Replacing the clip with a full-window region is the + // same as turning off clipping. + if (d->maskValid) + vgSeti(VG_MASKING, VG_FALSE); + d->maskValid = false; + d->maskIsSet = true; + d->maskRect = QRect(); + } else { + // Special case: if the intersection of the system + // clip and "r" is a single rectangle, then use the + // scissor for clipping. We try to avoid allocating a + // QRegion copy on the heap for the test if we can. + QRegion clip = d->systemClip; // Reference-counted, no alloc. + QRect clipRect; + if (clip.numRects() == 1) { + clipRect = clip.boundingRect().intersected(r); + } else if (clip.isEmpty()) { + clipRect = r; + } else { + clip = clip.intersect(r); + if (clip.numRects() != 1) { + d->maskValid = false; + d->maskIsSet = false; + d->maskRect = QRect(); + d->modifyMask(this, VG_FILL_MASK, r); + break; + } + clipRect = clip.boundingRect(); + } + d->maskValid = false; + d->maskIsSet = false; + d->maskRect = clipRect; + vgSeti(VG_MASKING, VG_FALSE); + updateScissor(); + } + } + break; + + case Qt::IntersectClip: + { + QRect r = d->transform.mapRect(rect); + if (d->maskIsSet && isDefaultClipRect(r)) { + // Intersecting a full-window clip with a full-window + // region is the same as turning off clipping. + if (d->maskValid) + vgSeti(VG_MASKING, VG_FALSE); + d->maskValid = false; + d->maskIsSet = true; + d->maskRect = QRect(); + } else { + d->modifyMask(this, VG_INTERSECT_MASK, r); + } + } + break; + + case Qt::UniteClip: + { + // If we already have a full-window clip, then uniting a + // region with it will do nothing. Otherwise union. + if (!(d->maskIsSet)) + d->modifyMask(this, VG_UNION_MASK, d->transform.mapRect(rect)); + } + break; + } } void QVGPaintEngine::clip(const QRegion ®ion, Qt::ClipOperation op) { Q_D(QVGPaintEngine); + // Use the QRect case if the region consists of a single rectangle. + if (region.numRects() == 1) { + clip(region.boundingRect(), op); + return; + } + d->dirty |= QPaintEngine::DirtyClipRegion; // If we have a non-simple transform, then use path-based clipping. @@ -1765,7 +1860,7 @@ void QVGPaintEnginePrivate::ensureMask maskRect = QRect(); } else { vgMask(VG_INVALID_HANDLE, VG_CLEAR_MASK, 0, 0, width, height); - if (!maskRect.isNull()) { + if (maskRect.isValid()) { vgMask(VG_INVALID_HANDLE, VG_FILL_MASK, maskRect.x(), height - maskRect.y() - maskRect.height(), maskRect.width(), maskRect.height()); @@ -1797,6 +1892,27 @@ void QVGPaintEnginePrivate::modifyMask maskIsSet = false; } +void QVGPaintEnginePrivate::modifyMask + (QVGPaintEngine *engine, VGMaskOperation op, const QRect& rect) +{ + QPaintDevice *pdev = engine->paintDevice(); + int width = pdev->width(); + int height = pdev->height(); + + if (!maskValid) + ensureMask(engine, width, height); + + if (rect.isValid()) { + vgMask(VG_INVALID_HANDLE, op, + rect.x(), height - rect.y() - rect.height(), + rect.width(), rect.height()); + } + + vgSeti(VG_MASKING, VG_TRUE); + maskValid = true; + maskIsSet = false; +} + #endif // !QVG_SCISSOR_CLIP void QVGPaintEngine::updateScissor() @@ -1892,6 +2008,16 @@ bool QVGPaintEngine::isDefaultClipRegion(const QRegion& region) rect.width() == width && rect.height() == height); } +bool QVGPaintEngine::isDefaultClipRect(const QRect& rect) +{ + QPaintDevice *pdev = paintDevice(); + int width = pdev->width(); + int height = pdev->height(); + + return (rect.x() == 0 && rect.y() == 0 && + rect.width() == width && rect.height() == height); +} + void QVGPaintEngine::clipEnabledChanged() { #if defined(QVG_SCISSOR_CLIP) diff --git a/src/openvg/qpaintengine_vg_p.h b/src/openvg/qpaintengine_vg_p.h index a390c80..bde06e5 100644 --- a/src/openvg/qpaintengine_vg_p.h +++ b/src/openvg/qpaintengine_vg_p.h @@ -154,6 +154,7 @@ private: void updateScissor(); QRegion defaultClipRegion(); bool isDefaultClipRegion(const QRegion& region); + bool isDefaultClipRect(const QRect& rect); bool clearRect(const QRectF &rect, const QColor &color); }; -- cgit v0.12 From 6c9647f6673fd5738001c5bbe416b116442fbc41 Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Thu, 2 Jul 2009 10:50:03 +1000 Subject: OpenVG: short-cut clipping for QPainterPath's that are just rects If the QPainterPath contains a structure that looks like a simple rectangle, then use the faster clip(QRect) function instead of a full VGPath-based render call. Task-number: QT-64 Reviewed-by: trustme --- src/openvg/qpaintengine_vg.cpp | 50 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp index 48953ac..7a962e4 100644 --- a/src/openvg/qpaintengine_vg.cpp +++ b/src/openvg/qpaintengine_vg.cpp @@ -1802,11 +1802,61 @@ void QVGPaintEngine::clip(const QRegion ®ion, Qt::ClipOperation op) } } +#if !defined(QVG_NO_RENDER_TO_MASK) + +// Copied from qpathclipper.cpp. +static bool qt_vg_pathToRect(const QPainterPath &path, QRectF *rect) +{ + if (path.elementCount() != 5) + return false; + + const bool mightBeRect = path.elementAt(0).isMoveTo() + && path.elementAt(1).isLineTo() + && path.elementAt(2).isLineTo() + && path.elementAt(3).isLineTo() + && path.elementAt(4).isLineTo(); + + if (!mightBeRect) + return false; + + const qreal x1 = path.elementAt(0).x; + const qreal y1 = path.elementAt(0).y; + + const qreal x2 = path.elementAt(1).x; + const qreal y2 = path.elementAt(2).y; + + if (path.elementAt(1).y != y1) + return false; + + if (path.elementAt(2).x != x2) + return false; + + if (path.elementAt(3).x != x1 || path.elementAt(3).y != y2) + return false; + + if (path.elementAt(4).x != x1 || path.elementAt(4).y != y1) + return false; + + if (rect) + *rect = QRectF(QPointF(x1, y1), QPointF(x2, y2)); + + return true; +} + +#endif + void QVGPaintEngine::clip(const QPainterPath &path, Qt::ClipOperation op) { #if !defined(QVG_NO_RENDER_TO_MASK) Q_D(QVGPaintEngine); + // If the path is a simple rectangle, then use clip(QRect) instead. + QRectF simpleRect; + if (qt_vg_pathToRect(path, &simpleRect)) { + clip(simpleRect.toRect(), op); + return; + } + d->dirty |= QPaintEngine::DirtyClipRegion; if (op == Qt::NoClip) { -- cgit v0.12 From cdfb2ed5096053314c0e23482609a1a491636ac1 Mon Sep 17 00:00:00 2001 From: Rohan McGovern Date: Thu, 2 Jul 2009 10:16:20 +1000 Subject: Improve cetest error reporting. Reviewed-by: Michael Goddard --- .../qtestlib/wince/cetest/activesyncconnection.cpp | 6 ++-- tools/qtestlib/wince/cetest/remoteconnection.cpp | 32 ++++++++++++++++++++++ tools/qtestlib/wince/cetest/remoteconnection.h | 2 ++ 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/tools/qtestlib/wince/cetest/activesyncconnection.cpp b/tools/qtestlib/wince/cetest/activesyncconnection.cpp index e8ca8f2..76e4a41 100644 --- a/tools/qtestlib/wince/cetest/activesyncconnection.cpp +++ b/tools/qtestlib/wince/cetest/activesyncconnection.cpp @@ -113,6 +113,8 @@ bool ActiveSyncConnection::copyFileToDevice(const QString &localSource, const QS CeCloseHandle(deviceHandle); return true; } + } else { + qWarning("Could not open %s: %s", qPrintable(localSource), qPrintable(file.errorString())); } return false; } @@ -120,7 +122,7 @@ bool ActiveSyncConnection::copyFileToDevice(const QString &localSource, const QS deleteFile(deviceDest); HANDLE deviceHandle = CeCreateFile(deviceDest.utf16(), GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); if (deviceHandle == INVALID_HANDLE_VALUE) { - debugOutput(QString::fromLatin1(" Could not create target file"), 2); + qWarning("Could not create %s: %s", qPrintable(deviceDest), strwinerror(CeGetLastError()).constData()); return false; } @@ -144,7 +146,7 @@ bool ActiveSyncConnection::copyFileToDevice(const QString &localSource, const QS if (toWrite == 0) break; if (!CeWriteFile(deviceHandle, data.data() , toWrite, &written, NULL)) { - debugOutput(QString::fromLatin1(" Could not write File"), 2); + qWarning("Could not write to %s: %s", qPrintable(deviceDest), strwinerror(CeGetLastError()).constData()); return false; } currentPos += written; diff --git a/tools/qtestlib/wince/cetest/remoteconnection.cpp b/tools/qtestlib/wince/cetest/remoteconnection.cpp index 547b211..75788e2 100644 --- a/tools/qtestlib/wince/cetest/remoteconnection.cpp +++ b/tools/qtestlib/wince/cetest/remoteconnection.cpp @@ -41,6 +41,38 @@ #include "remoteconnection.h" +QByteArray strwinerror(DWORD errorcode) +{ + QByteArray out(512, 0); + + DWORD ok = FormatMessageA( + FORMAT_MESSAGE_FROM_SYSTEM, + 0, + errorcode, + 0, + out.data(), + out.size(), + 0 + ); + + if (!ok) { + qsnprintf(out.data(), out.size(), + "(error %d; additionally, error %d while looking up error string)", + (int)errorcode, (int)GetLastError()); + } + else { + out.resize(qstrlen(out.constData())); + if (out.endsWith("\r\n")) + out.chop(2); + + /* Append error number to error message for good measure */ + out.append(" ("); + out.append(QByteArray::number((int)errorcode)); + out.append(")"); + } + return out; +} + AbstractRemoteConnection::AbstractRemoteConnection() { } diff --git a/tools/qtestlib/wince/cetest/remoteconnection.h b/tools/qtestlib/wince/cetest/remoteconnection.h index 9c3e63d..f517009 100644 --- a/tools/qtestlib/wince/cetest/remoteconnection.h +++ b/tools/qtestlib/wince/cetest/remoteconnection.h @@ -79,4 +79,6 @@ public: virtual bool execute(QString program, QString arguments = QString(), int timeout = -1, int *returnValue = NULL) = 0; }; +QByteArray strwinerror(DWORD); + #endif -- cgit v0.12 From fb1fa68ae8555deeaeaf6f193c678269c85ffc4d Mon Sep 17 00:00:00 2001 From: Rohan McGovern Date: Thu, 2 Jul 2009 11:42:25 +1000 Subject: Let QtRemote report the error code to cetest when creating the test process fails. This gives some hint to the user in the case of problems like missing DLLs, as opposed to silent failure. Reviewed-by: Michael Goddard --- tools/qtestlib/wince/cetest/activesyncconnection.cpp | 14 ++++++++++++-- tools/qtestlib/wince/remotelib/commands.cpp | 10 ++++++++-- tools/qtestlib/wince/remotelib/commands.h | 2 +- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/tools/qtestlib/wince/cetest/activesyncconnection.cpp b/tools/qtestlib/wince/cetest/activesyncconnection.cpp index 76e4a41..99fac2c 100644 --- a/tools/qtestlib/wince/cetest/activesyncconnection.cpp +++ b/tools/qtestlib/wince/cetest/activesyncconnection.cpp @@ -382,6 +382,7 @@ bool ActiveSyncConnection::execute(QString program, QString arguments, int timeo BYTE* output; IRAPIStream *stream; int returned = 0; + DWORD error = 0; HRESULT res = CeRapiInvoke(dllLocation.utf16(), functionName.utf16(), 0, 0, &outputSize, &output, &stream, 0); if (S_OK != res) { if (S_OK != CeGetLastError()) @@ -416,9 +417,18 @@ bool ActiveSyncConnection::execute(QString program, QString arguments, int timeo if (S_OK != stream->Read(&returned, sizeof(returned), &written)) { qWarning(" Could not access return value of process"); } - result = true; - } + if (S_OK != stream->Read(&error, sizeof(error), &written)) { + qWarning(" Could not access error code"); + } + if (error) { + qWarning() << "Error on target:" << strwinerror(error); + result = false; + } + else { + result = true; + } + } if (returnValue) *returnValue = returned; diff --git a/tools/qtestlib/wince/remotelib/commands.cpp b/tools/qtestlib/wince/remotelib/commands.cpp index 3aed2d6..f2176dd 100644 --- a/tools/qtestlib/wince/remotelib/commands.cpp +++ b/tools/qtestlib/wince/remotelib/commands.cpp @@ -56,6 +56,7 @@ int qRemoteLaunch(DWORD, BYTE*, DWORD*, BYTE**, IRAPIStream* stream) wchar_t* arguments = 0; int timeout = -1; int returnValue = -2; + DWORD error = 0; if (S_OK != stream->Read(&appLength, sizeof(appLength), &bytesRead)) CLEAN_FAIL(-2); @@ -74,11 +75,13 @@ int qRemoteLaunch(DWORD, BYTE*, DWORD*, BYTE**, IRAPIStream* stream) if (S_OK != stream->Read(&timeout, sizeof(timeout), &bytesRead)) CLEAN_FAIL(-2); - bool result = qRemoteExecute(appName, arguments, &returnValue, timeout); + bool result = qRemoteExecute(appName, arguments, &returnValue, &error, timeout); if (timeout != 0) { if (S_OK != stream->Write(&returnValue, sizeof(returnValue), &bytesRead)) CLEAN_FAIL(-4); + if (S_OK != stream->Write(&error, sizeof(error), &bytesRead)) + CLEAN_FAIL(-5); } delete appName; delete arguments; @@ -90,13 +93,16 @@ int qRemoteLaunch(DWORD, BYTE*, DWORD*, BYTE**, IRAPIStream* stream) } -bool qRemoteExecute(const wchar_t* program, const wchar_t* arguments, int *returnValue, int timeout) +bool qRemoteExecute(const wchar_t* program, const wchar_t* arguments, int *returnValue, DWORD* error, int timeout) { + *error = 0; + if (!program) return false; PROCESS_INFORMATION pid; if (!CreateProcess(program, arguments, NULL, NULL, false, 0, NULL, NULL, NULL, &pid)) { + *error = GetLastError(); wprintf(L"Could not launch: %s\n", program); return false; } diff --git a/tools/qtestlib/wince/remotelib/commands.h b/tools/qtestlib/wince/remotelib/commands.h index 9f0b2e3..5275f2c 100644 --- a/tools/qtestlib/wince/remotelib/commands.h +++ b/tools/qtestlib/wince/remotelib/commands.h @@ -45,7 +45,7 @@ extern "C" { int __declspec(dllexport) qRemoteLaunch(DWORD, BYTE*, DWORD*, BYTE**, IRAPIStream*); - bool __declspec(dllexport) qRemoteExecute(const wchar_t* program, const wchar_t* arguments = NULL, int *returnValue = NULL , int timeout = -1); + bool __declspec(dllexport) qRemoteExecute(const wchar_t* program, const wchar_t* arguments = NULL, int *returnValue = NULL , DWORD* error = NULL, int timeout = -1); } #endif -- cgit v0.12 From f126b8cc5733d2cd37dd2aad9119e482b0d4a0e6 Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Thu, 2 Jul 2009 08:39:57 +0200 Subject: doc: Corrected several qdoc warnings. --- src/gui/graphicsview/qgraphicssceneevent.cpp | 35 ++++++++++++++-------------- src/gui/itemviews/qheaderview.h | 2 +- src/gui/kernel/qapplication.cpp | 2 +- src/qt3support/widgets/q3datetimeedit.cpp | 7 +++--- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/gui/graphicsview/qgraphicssceneevent.cpp b/src/gui/graphicsview/qgraphicssceneevent.cpp index 7906fb8..338f12a 100644 --- a/src/gui/graphicsview/qgraphicssceneevent.cpp +++ b/src/gui/graphicsview/qgraphicssceneevent.cpp @@ -1875,12 +1875,12 @@ void QGraphicsSceneGestureEvent::setGestures(const QSet &gestures) } /*! - Sets the accept flag of the all gestures inside the event object, - the equivalent of calling \l{QEvent::accept()}{accept()} or - \l{QEvent::setAccepted()}{setAccepted(true)}. + Sets the accept flag of the all gestures for the event object. + This is the equivalent of calling \l{QEvent::accept()} {accept()} + or \l{QEvent::setAccepted()}{setAccepted(true)}. - Setting the accept parameter indicates that the event receiver - wants the gesture. Unwanted gestures might be propagated to the parent + Setting the accept flag indicates that the event receiver wants + the gesture. Unwanted gestures might be propagated to the parent widget. */ void QGraphicsSceneGestureEvent::acceptAll() @@ -1893,13 +1893,14 @@ void QGraphicsSceneGestureEvent::acceptAll() } /*! - Sets the accept flag of the specified gesture inside the event - object, the equivalent of calling - \l{QGestureEvent::gesture()}{gesture(type)}->\l{QGesture::accept()}{accept()} - Setting the accept parameter indicates that the event receiver - wants the gesture. Unwanted gestures might be propagated to the parent - widget. + Sets the accept flag of the gesture specified by \a type. This is + equivalent to calling \l{QGestureEvent::gesture()} {gesture(type)}-> + \l{QGesture::accept()}{accept()} + + Setting the accept flag indicates that the event receiver + wants the gesture. Unwanted gestures might be propagated to the parent + widget. */ void QGraphicsSceneGestureEvent::accept(Qt::GestureType type) { @@ -1908,13 +1909,13 @@ void QGraphicsSceneGestureEvent::accept(Qt::GestureType type) } /*! - Sets the accept flag of the specified gesture inside the event - object, the equivalent of calling - \l{QGestureEvent::gesture()}{gesture(type)}->\l{QGesture::accept()}{accept()} - Setting the accept parameter indicates that the event receiver - wants the gesture. Unwanted gestures might be propagated to the parent - widget. + Sets the accept flag of the gesture specified by \a type. This is + equivalent to calling \l{QGestureEvent::gesture()} {gesture(type)}-> + \l{QGesture::accept()}{accept()} + + Setting the accept flag indicates that the event receiver wants the + gesture. Unwanted gestures might be propagated to the parent widget. */ void QGraphicsSceneGestureEvent::accept(const QString &type) { diff --git a/src/gui/itemviews/qheaderview.h b/src/gui/itemviews/qheaderview.h index f752ae2..bf92667 100644 --- a/src/gui/itemviews/qheaderview.h +++ b/src/gui/itemviews/qheaderview.h @@ -221,7 +221,7 @@ protected: bool isIndexHidden(const QModelIndex &index) const; QModelIndex moveCursor(CursorAction, Qt::KeyboardModifiers); - void setSelection(const QRect&, QItemSelectionModel::SelectionFlags); + void setSelection(const QRect& rect, QItemSelectionModel::SelectionFlags flags); QRegion visualRegionForSelection(const QItemSelection &selection) const; void initStyleOption(QStyleOptionHeader *option) const; diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 15ddce8..60c69cc 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -5096,7 +5096,7 @@ void QApplication::removeGestureRecognizer(QGestureRecognizer *recognizer) The delay allows to postpone widget's input event handling until gestures framework can successfully recognize a gesture. - \sa QWidget::grabGesture + \sa QWidget::grabGesture() */ void QApplication::setEventDeliveryDelayForGestures(int delay) { diff --git a/src/qt3support/widgets/q3datetimeedit.cpp b/src/qt3support/widgets/q3datetimeedit.cpp index 4872642..9c2f289 100644 --- a/src/qt3support/widgets/q3datetimeedit.cpp +++ b/src/qt3support/widgets/q3datetimeedit.cpp @@ -2648,13 +2648,12 @@ Q3DateTimeEdit::~Q3DateTimeEdit() } -/*! +/*! \fn void Q3DateTimeEdit::resizeEvent(QResizeEvent *event) \reimp - Intercepts and handles resize events which have special meaning - for the Q3DateTimeEdit. + Intercepts and handles the resize \a event, which hase a + special meaning for the Q3DateTimeEdit. */ - void Q3DateTimeEdit::resizeEvent(QResizeEvent *) { int dw = de->sizeHint().width(); -- cgit v0.12 From 058c4f1cfd0536779ec99f3d89bdd90bf52ae20e Mon Sep 17 00:00:00 2001 From: Rohan McGovern Date: Thu, 2 Jul 2009 12:58:51 +1000 Subject: Let cetest deploy libraries other than for Qt to make it usable for running unit tests for projects outside of Qt. Let cetest look in the paths given with `-L' in LIBS, and to deploy libraries whose names don't start with `Qt'. This also fixes deployment of Qt autotests which link against phonon (the only Qt library whose name doesn't start with `Qt'). Reviewed-by: mauricek --- tools/qtestlib/wince/cetest/deployment.cpp | 34 +++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/tools/qtestlib/wince/cetest/deployment.cpp b/tools/qtestlib/wince/cetest/deployment.cpp index fec2735..68f0197 100644 --- a/tools/qtestlib/wince/cetest/deployment.cpp +++ b/tools/qtestlib/wince/cetest/deployment.cpp @@ -125,13 +125,37 @@ void DeploymentHandler::initQtDeploy(QMakeProject *project, DeploymentList &depl if (!project->values("QMAKE_QT_DLL").isEmpty() && !project->values("QMAKE_LIBDIR").isEmpty()) { QStringList libs = project->values("LIBS"); QStringList qtLibs; + QStringList libPaths; foreach (QString item, libs) { - if (item.startsWith("-lQt")) { - qtLibs += project->values("QMAKE_LIBDIR").at(0) + QDir::separator() + item.mid(2) + QLatin1String("4.dll"); + + if (item.startsWith("-L")) { + // -L -> a directory containing DLLs + libPaths << item.mid(2); + continue; + } + + QStringList libCandidates; + + if (item.startsWith("-l")) { + // -l -> a library located within one of the standard library paths + QString lib = item.mid(2); + + // Check if it's a Qt library first, then check in all paths given with -L. + // Note Qt libraries get a `4' appended to them, others don't. + libCandidates << project->values("QMAKE_LIBDIR").at(0) + QDir::separator() + lib + QLatin1String("4.dll"); + foreach (QString const& libPath, libPaths) { + libCandidates << libPath + QDir::separator() + lib + QLatin1String(".dll"); + } } else { - QFileInfo info(item); - if (info.exists() && info.isAbsolute() && info.fileName().startsWith(QLatin1String("Qt"))) - qtLibs += info.dir().absoluteFilePath(info.fileName().replace(QLatin1String(".lib"), QLatin1String(".dll"))); + libCandidates << item.replace(".lib",".dll"); + } + + foreach (QString const& file, libCandidates) { + QFileInfo info(file); + if (info.exists()) { + qtLibs += info.dir().absoluteFilePath(info.fileName()); + break; + } } } for (QStringList::ConstIterator it = qtLibs.constBegin(); it != qtLibs.constEnd(); ++it) { -- cgit v0.12 From b4028f5a2195a432059ff26c288d772af47bc14d Mon Sep 17 00:00:00 2001 From: Rohan McGovern Date: Thu, 2 Jul 2009 17:03:31 +1000 Subject: Fixed cetest compile. --- tools/qtestlib/wince/cetest/activesyncconnection.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qtestlib/wince/cetest/activesyncconnection.cpp b/tools/qtestlib/wince/cetest/activesyncconnection.cpp index 99fac2c..0f98619 100644 --- a/tools/qtestlib/wince/cetest/activesyncconnection.cpp +++ b/tools/qtestlib/wince/cetest/activesyncconnection.cpp @@ -422,7 +422,7 @@ bool ActiveSyncConnection::execute(QString program, QString arguments, int timeo } if (error) { - qWarning() << "Error on target:" << strwinerror(error); + qWarning("Error on target: %s", strwinerror(error).constData()); result = false; } else { -- cgit v0.12 From 5fc3fe2e3f04475ac8c0e3287af6042bd8b67c57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 2 Jul 2009 09:56:13 +0200 Subject: Dont include untransformable graphics items twice. This revertes d39a62720ba67a0fa6e4e37519d22f14c7b7404e (we had to do it with the old implementation, but the new one have untransformable items included in the indexed list. The only difference is that untransformable items are also in the untransformable list; otherwise in the bsp tree). Auto-test included. --- .../graphicsview/qgraphicsscenebsptreeindex.cpp | 1 - .../tst_qgraphicssceneindex.cpp | 39 ++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp index ff9a3da..c8d755e 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -606,7 +606,6 @@ QList QGraphicsSceneBspTreeIndex::items(Qt::SortOrder order) co itemList << item; } } - itemList += d->untransformableItems; if (order != -1) { //We sort descending order d->sortItems(&itemList, order, d->sortCacheEnabled); diff --git a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp index 9d0675d..3ce5b16 100644 --- a/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp +++ b/tests/auto/qgraphicssceneindex/tst_qgraphicssceneindex.cpp @@ -65,6 +65,7 @@ private slots: void movingItems_data(); void movingItems(); void connectedToSceneRectChanged(); + void items(); private: void common_data(); @@ -228,5 +229,43 @@ void tst_QGraphicsSceneIndex::connectedToSceneRectChanged() QCOMPARE(scene.receivers(SIGNAL(sceneRectChanged(const QRectF&))), 1); } +void tst_QGraphicsSceneIndex::items() +{ + QGraphicsScene scene; + QGraphicsItem *item1 = scene.addRect(0, 0, 10, 10); + QGraphicsItem *item2 = scene.addRect(10, 10, 10, 10); + QCOMPARE(scene.items().size(), 2); + + // Move from unindexed items into bsp tree. + QTest::qWait(50); + QCOMPARE(scene.items().size(), 2); + + // Add untransformable item. + QGraphicsItem *item3 = new QGraphicsRectItem(QRectF(20, 20, 10, 10)); + item3->setFlag(QGraphicsItem::ItemIgnoresTransformations); + scene.addItem(item3); + QCOMPARE(scene.items().size(), 3); + + // Move from unindexed items into untransformable items. + QTest::qWait(50); + QCOMPARE(scene.items().size(), 3); + + // Move from untransformable items into unindexed items. + item3->setFlag(QGraphicsItem::ItemIgnoresTransformations, false); + QCOMPARE(scene.items().size(), 3); + QTest::qWait(50); + QCOMPARE(scene.items().size(), 3); + + // Make all items untransformable. + item1->setFlag(QGraphicsItem::ItemIgnoresTransformations); + item2->setParentItem(item1); + item3->setParentItem(item2); + QCOMPARE(scene.items().size(), 3); + + // Move from unindexed items into untransformable items. + QTest::qWait(50); + QCOMPARE(scene.items().size(), 3); +} + QTEST_MAIN(tst_QGraphicsSceneIndex) #include "tst_qgraphicssceneindex.moc" -- cgit v0.12 From 69083610b09aaabbff5e8a177fac713a6a6d46ba Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Thu, 2 Jul 2009 10:38:08 +0200 Subject: doc: Corrected several qdoc warnings. --- src/gui/graphicsview/qgraphicssceneevent.cpp | 5 ++++- src/gui/kernel/qevent.cpp | 4 ++++ src/gui/kernel/qgesturerecognizer.cpp | 7 ++++--- src/qt3support/sql/q3datatable.cpp | 2 -- tools/qdoc3/test/qt-cpp-ignore.qdocconf | 3 ++- tools/qdoc3/test/qt-inc.qdocconf | 3 ++- 6 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/gui/graphicsview/qgraphicssceneevent.cpp b/src/gui/graphicsview/qgraphicssceneevent.cpp index 338f12a..27a2d7e 100644 --- a/src/gui/graphicsview/qgraphicssceneevent.cpp +++ b/src/gui/graphicsview/qgraphicssceneevent.cpp @@ -1892,8 +1892,11 @@ void QGraphicsSceneGestureEvent::acceptAll() setAccepted(true); } -/*! +/*! \fn void QGraphicsSceneGestureEvent::accept() + Calls QEvent::accept(). +*/ +/*! Sets the accept flag of the gesture specified by \a type. This is equivalent to calling \l{QGestureEvent::gesture()} {gesture(type)}-> \l{QGesture::accept()}{accept()} diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index e40ad9d..a7a7f2d 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -3628,6 +3628,10 @@ QSet QGestureEvent::cancelledGestures() const return m_cancelledGestures; } +/*! \fn void QGestureEvent::accept() + Calls QEvent::accept(). +*/ + /*! Sets the accept flag of the all gestures inside the event object, the equivalent of calling \l{QEvent::accept()}{accept()} or diff --git a/src/gui/kernel/qgesturerecognizer.cpp b/src/gui/kernel/qgesturerecognizer.cpp index c330663..30889d7 100644 --- a/src/gui/kernel/qgesturerecognizer.cpp +++ b/src/gui/kernel/qgesturerecognizer.cpp @@ -97,8 +97,8 @@ QString qt_getStandardGestureTypeName(Qt::GestureType gestureType); This is a pure virtual function that needs to be implemented in subclasses. - Parses input \a event and returns the result, which specifies if - the event sequence is a gesture or not. + Parses input \a event and returns the result, which specifies + whether the event sequence is a gesture or not. */ /*! \fn QGesture* QGestureRecognizer::getGesture() @@ -123,7 +123,8 @@ QString qt_getStandardGestureTypeName(Qt::GestureType gestureType); The gesture recognizer might emit the stateChanged() signal when the gesture state changes asynchronously, i.e. without any event - being filtered through filterEvent(). + being filtered through filterEvent(). \a result specifies whether + the event sequence is a gesture or not. */ QGestureRecognizerPrivate::QGestureRecognizerPrivate() diff --git a/src/qt3support/sql/q3datatable.cpp b/src/qt3support/sql/q3datatable.cpp index 638aff8..d8d3c2b 100644 --- a/src/qt3support/sql/q3datatable.cpp +++ b/src/qt3support/sql/q3datatable.cpp @@ -1726,8 +1726,6 @@ void Q3DataTable::repaintCell( int row, int col ) the content coordinate system. If \a selected is true the cell has been selected and would normally be rendered differently than an unselected cell. - - \sa QSql::isNull() */ void Q3DataTable::paintCell( QPainter * p, int row, int col, const QRect & cr, diff --git a/tools/qdoc3/test/qt-cpp-ignore.qdocconf b/tools/qdoc3/test/qt-cpp-ignore.qdocconf index 9a18abe..709e336 100644 --- a/tools/qdoc3/test/qt-cpp-ignore.qdocconf +++ b/tools/qdoc3/test/qt-cpp-ignore.qdocconf @@ -68,7 +68,8 @@ Cpp.ignoretokens = QAXFACTORY_EXPORT \ QT_END_NAMESPACE \ QT_END_INCLUDE_NAMESPACE \ PHONON_EXPORT \ - Q_GADGET + Q_GADGET \ + QWEBKIT_EXPORT Cpp.ignoredirectives = Q_DECLARE_HANDLE \ Q_DECLARE_INTERFACE \ Q_DECLARE_METATYPE \ diff --git a/tools/qdoc3/test/qt-inc.qdocconf b/tools/qdoc3/test/qt-inc.qdocconf index 01b07b3..542c7ca 100644 --- a/tools/qdoc3/test/qt-inc.qdocconf +++ b/tools/qdoc3/test/qt-inc.qdocconf @@ -100,7 +100,8 @@ Cpp.ignoretokens = QAXFACTORY_EXPORT \ Q_TYPENAME \ Q_XML_EXPORT \ QDBUS_EXPORT \ - Q_GADGET + Q_GADGET \ + QWEBKIT_EXPORT Cpp.ignoredirectives = Q_DECLARE_HANDLE \ Q_DECLARE_INTERFACE \ Q_DECLARE_METATYPE \ -- cgit v0.12 From 6d71de4283c05b1b42ef26fe4c23334ad34c8a54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 2 Jul 2009 10:46:37 +0200 Subject: Kill dead BSP tree code in graphics view. --- src/gui/graphicsview/qgraphicsscene_bsp.cpp | 41 ----------------------------- src/gui/graphicsview/qgraphicsscene_bsp_p.h | 3 --- 2 files changed, 44 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene_bsp.cpp b/src/gui/graphicsview/qgraphicsscene_bsp.cpp index 5858eab..7d30749 100644 --- a/src/gui/graphicsview/qgraphicsscene_bsp.cpp +++ b/src/gui/graphicsview/qgraphicsscene_bsp.cpp @@ -154,17 +154,6 @@ QList QGraphicsSceneBspTree::items(const QRectF &rect) const return tmp; } -QList QGraphicsSceneBspTree::items(const QPointF &pos) const -{ - QList tmp; - findVisitor->foundItems = &tmp; - climbTree(findVisitor, pos); - // Reset discovery bits. - for (int i = 0; i < tmp.size(); ++i) - tmp.at(i)->d_ptr->itemDiscovered = 0; - return tmp; -} - int QGraphicsSceneBspTree::leafCount() const { return leafCnt; @@ -241,36 +230,6 @@ void QGraphicsSceneBspTree::initialize(const QRectF &rect, int depth, int index) } } -void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QPointF &pos, int index) const -{ - if (nodes.isEmpty()) - return; - - const Node &node = nodes.at(index); - const int childIndex = firstChildIndex(index); - - switch (node.type) { - case Node::Leaf: { - visitor->visit(const_cast*>(&leaves[node.leafIndex])); - break; - } - case Node::Vertical: - if (pos.x() < node.offset) { - climbTree(visitor, pos, childIndex); - } else { - climbTree(visitor, pos, childIndex + 1); - } - break; - case Node::Horizontal: - if (pos.y() < node.offset) { - climbTree(visitor, pos, childIndex); - } else { - climbTree(visitor, pos, childIndex + 1); - } - break; - } -} - void QGraphicsSceneBspTree::climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QRectF &rect, int index) const { if (nodes.isEmpty()) diff --git a/src/gui/graphicsview/qgraphicsscene_bsp_p.h b/src/gui/graphicsview/qgraphicsscene_bsp_p.h index 323cf04..24b926c 100644 --- a/src/gui/graphicsview/qgraphicsscene_bsp_p.h +++ b/src/gui/graphicsview/qgraphicsscene_bsp_p.h @@ -93,7 +93,6 @@ public: void removeItems(const QSet &items); QList items(const QRectF &rect) const; - QList items(const QPointF &pos) const; int leafCount() const; inline int firstChildIndex(int index) const @@ -106,11 +105,9 @@ public: private: void initialize(const QRectF &rect, int depth, int index); - void climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QPointF &pos, int index = 0) const; void climbTree(QGraphicsSceneBspTreeVisitor *visitor, const QRectF &rect, int index = 0) const; void findItems(QList *foundItems, const QRectF &rect, int index); - void findItems(QList *foundItems, const QPointF &pos, int index); QRectF rectForIndex(int index) const; QVector nodes; -- cgit v0.12 From ad637177fa62f6ac92b653735bc2f743d7af2851 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Thu, 2 Jul 2009 11:10:36 +0200 Subject: add a few QObject binding tests --- tests/auto/qscriptqobject/tst_qscriptqobject.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tests/auto/qscriptqobject/tst_qscriptqobject.cpp b/tests/auto/qscriptqobject/tst_qscriptqobject.cpp index 14d3283..ee914ab 100644 --- a/tests/auto/qscriptqobject/tst_qscriptqobject.cpp +++ b/tests/auto/qscriptqobject/tst_qscriptqobject.cpp @@ -605,6 +605,12 @@ void tst_QScriptExtQObject::getSetStaticProperty() QVERIFY(!(mobj.propertyFlags("mySlot") & QScriptValue::Undeletable)); QVERIFY(!(mobj.propertyFlags("mySlot") & QScriptValue::SkipInEnumeration)); QVERIFY(mobj.propertyFlags("mySlot") & QScriptValue::QObjectMember); + + // signature-based property + QVERIFY(!(mobj.propertyFlags("mySlot()") & QScriptValue::ReadOnly)); + QVERIFY(!(mobj.propertyFlags("mySlot()") & QScriptValue::Undeletable)); + QVERIFY(!(mobj.propertyFlags("mySlot()") & QScriptValue::SkipInEnumeration)); + QVERIFY(mobj.propertyFlags("mySlot()") & QScriptValue::QObjectMember); } // property change in C++ should be reflected in script @@ -847,6 +853,9 @@ void tst_QScriptExtQObject::getSetStaticProperty() QVERIFY(slot.isFunction()); QScriptValue sameSlot = m_engine->evaluate("myObject.mySlot"); QVERIFY(sameSlot.strictlyEquals(slot)); + sameSlot = m_engine->evaluate("myObject['mySlot()']"); + QEXPECT_FAIL("", "Signature-based method lookup creates new function wrapper object", Continue); + QVERIFY(sameSlot.strictlyEquals(slot)); } } @@ -897,6 +906,20 @@ void tst_QScriptExtQObject::getSetChildren() QCOMPARE(m_engine->evaluate("myObject.hasOwnProperty('child')") .strictlyEquals(QScriptValue(m_engine, true)), true); + QScriptValue mobj = m_engine->evaluate("myObject"); + QVERIFY(mobj.propertyFlags("child") & QScriptValue::ReadOnly); + QVERIFY(mobj.propertyFlags("child") & QScriptValue::Undeletable); + QVERIFY(mobj.propertyFlags("child") & QScriptValue::SkipInEnumeration); + QVERIFY(!(mobj.propertyFlags("child") & QScriptValue::QObjectMember)); + + { + QScriptValue scriptChild = m_engine->evaluate("myObject.child"); + QVERIFY(scriptChild.isQObject()); + QCOMPARE(scriptChild.toQObject(), (QObject*)child); + QScriptValue sameChild = m_engine->evaluate("myObject.child"); + QVERIFY(sameChild.strictlyEquals(scriptChild)); + } + // add a grandchild MyQObject *grandChild = new MyQObject(child); grandChild->setObjectName("grandChild"); -- cgit v0.12 From cd4901b1e3a545d025628e881a143b8f240d2690 Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Thu, 2 Jul 2009 11:37:53 +0200 Subject: doc: Corrected several qdoc warnings. --- doc/src/qnamespace.qdoc | 3 +++ src/gui/kernel/qapplication.cpp | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/doc/src/qnamespace.qdoc b/doc/src/qnamespace.qdoc index 805855a..e77cc7e 100644 --- a/doc/src/qnamespace.qdoc +++ b/doc/src/qnamespace.qdoc @@ -1208,6 +1208,9 @@ handle touch events. Without this attribute set, events from a touch device will be sent as mouse events. + \value WA_TouchPadAcceptSingleTouchEvents Allows touchpad single + touch events to be sent to the widget. + \omitvalue WA_SetLayoutDirection \omitvalue WA_InputMethodTransparent \omitvalue WA_WState_CompressKeys diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 60c69cc..a7b7a0a 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -5064,7 +5064,7 @@ bool QApplicationPrivate::shouldSetFocus(QWidget *w, Qt::FocusPolicy policy) Qt takes ownership of the provided \a recognizer. - \sa Qt::AA_EnableGestures, QGestureEvent + \sa QGestureEvent */ void QApplication::addGestureRecognizer(QGestureRecognizer *recognizer) { @@ -5076,7 +5076,7 @@ void QApplication::addGestureRecognizer(QGestureRecognizer *recognizer) Removes custom gesture \a recognizer object. - \sa Qt::AA_EnableGestures, QGestureEvent + \sa QGestureEvent */ void QApplication::removeGestureRecognizer(QGestureRecognizer *recognizer) { -- cgit v0.12 From 11ef1b9bae383c46f7893db0d26c99d354642609 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 30 Jun 2009 20:50:32 +0200 Subject: Add a function to check if an interface is implemented by an object. Also reorganise a bit, moving the function to create the interface name from an object's class name to qdbusmisc.cpp too. Reviewed-By: Trust Me --- src/dbus/qdbusconnection_p.h | 5 ++--- src/dbus/qdbusintegrator.cpp | 8 ++----- src/dbus/qdbusmisc.cpp | 47 ++++++++++++++++++++++++++++++++++++++++++ src/dbus/qdbusxmlgenerator.cpp | 37 --------------------------------- 4 files changed, 51 insertions(+), 46 deletions(-) diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h index 5c37509..a156a71 100644 --- a/src/dbus/qdbusconnection_p.h +++ b/src/dbus/qdbusconnection_p.h @@ -300,6 +300,8 @@ public: extern int qDBusParametersForMethod(const QMetaMethod &mm, QList& metaTypes); extern int qDBusNameToTypeId(const char *name); extern bool qDBusCheckAsyncTag(const char *tag); +extern bool qDBusInterfaceInObject(QObject *obj, const QString &interface_name); +extern QString qDBusInterfaceFromMetaObject(const QMetaObject *mo); // in qdbusinternalfilters.cpp extern QString qDBusIntrospectObject(const QDBusConnectionPrivate::ObjectTreeNode &node); @@ -310,9 +312,6 @@ extern QDBusMessage qDBusPropertySet(const QDBusConnectionPrivate::ObjectTreeNod extern QDBusMessage qDBusPropertyGetAll(const QDBusConnectionPrivate::ObjectTreeNode &node, const QDBusMessage &msg); -// in qdbusxmlgenerator.cpp -extern QString qDBusInterfaceFromMetaObject(const QMetaObject *mo); - QT_END_NAMESPACE #endif diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index 0578bf1..76179c9 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -1359,12 +1359,8 @@ void QDBusConnectionPrivate::activateObject(ObjectTreeNode &node, const QDBusMes // try the object itself: if (node.flags & (QDBusConnection::ExportScriptableSlots|QDBusConnection::ExportNonScriptableSlots)) { bool interfaceFound = true; - if (!msg.interface().isEmpty()) { - // check if the interface name matches anything in the class hierarchy - const QMetaObject *mo = node.obj->metaObject(); - for ( ; !interfaceFound && mo != &QObject::staticMetaObject; mo = mo->superClass()) - interfaceFound = msg.interface() == qDBusInterfaceFromMetaObject(mo); - } + if (!msg.interface().isEmpty()) + interfaceFound = qDBusInterfaceInObject(node.obj, msg.interface()); if (interfaceFound) { if (!activateCall(node.obj, node.flags, msg)) diff --git a/src/dbus/qdbusmisc.cpp b/src/dbus/qdbusmisc.cpp index e5c1da6..1b77a9b 100644 --- a/src/dbus/qdbusmisc.cpp +++ b/src/dbus/qdbusmisc.cpp @@ -41,12 +41,14 @@ #include +#include #include #include #include "qdbusutil_p.h" #include "qdbusconnection_p.h" #include "qdbusmetatype_p.h" +#include "qdbusabstractadaptor_p.h" // for QCLASSINFO_DBUS_* QT_BEGIN_NAMESPACE @@ -73,6 +75,51 @@ int qDBusNameToTypeId(const char *name) return id; } +QString qDBusInterfaceFromMetaObject(const QMetaObject *mo) +{ + QString interface; + + int idx = mo->indexOfClassInfo(QCLASSINFO_DBUS_INTERFACE); + if (idx >= mo->classInfoOffset()) { + interface = QLatin1String(mo->classInfo(idx).value()); + } else { + interface = QLatin1String(mo->className()); + interface.replace(QLatin1String("::"), QLatin1String(".")); + + if (interface.startsWith(QLatin1String("QDBus"))) { + interface.prepend(QLatin1String("com.trolltech.QtDBus.")); + } else if (interface.startsWith(QLatin1Char('Q')) && + interface.length() >= 2 && interface.at(1).isUpper()) { + // assume it's Qt + interface.prepend(QLatin1String("com.trolltech.Qt.")); + } else if (!QCoreApplication::instance()|| + QCoreApplication::instance()->applicationName().isEmpty()) { + interface.prepend(QLatin1String("local.")); + } else { + interface.prepend(QLatin1Char('.')).prepend(QCoreApplication::instance()->applicationName()); + QStringList domainName = + QCoreApplication::instance()->organizationDomain().split(QLatin1Char('.'), + QString::SkipEmptyParts); + if (domainName.isEmpty()) + interface.prepend(QLatin1String("local.")); + else + for (int i = 0; i < domainName.count(); ++i) + interface.prepend(QLatin1Char('.')).prepend(domainName.at(i)); + } + } + + return interface; +} + +bool qDBusInterfaceInObject(QObject *obj, const QString &interface_name) +{ + const QMetaObject *mo = obj->metaObject(); + for ( ; mo != &QObject::staticMetaObject; mo = mo->superClass()) + if (interface_name == qDBusInterfaceFromMetaObject(mo)) + return true; + return false; +} + // calculates the metatypes for the method // the slot must have the parameters in the following form: // - zero or more value or const-ref parameters of any kind diff --git a/src/dbus/qdbusxmlgenerator.cpp b/src/dbus/qdbusxmlgenerator.cpp index 82bd762..b426abd 100644 --- a/src/dbus/qdbusxmlgenerator.cpp +++ b/src/dbus/qdbusxmlgenerator.cpp @@ -39,7 +39,6 @@ ** ****************************************************************************/ -#include #include #include @@ -232,42 +231,6 @@ static QString generateInterfaceXml(const QMetaObject *mo, int flags, int method return retval; } -QString qDBusInterfaceFromMetaObject(const QMetaObject *mo) -{ - QString interface; - - int idx = mo->indexOfClassInfo(QCLASSINFO_DBUS_INTERFACE); - if (idx >= mo->classInfoOffset()) { - interface = QLatin1String(mo->classInfo(idx).value()); - } else { - interface = QLatin1String(mo->className()); - interface.replace(QLatin1String("::"), QLatin1String(".")); - - if (interface.startsWith(QLatin1String("QDBus"))) { - interface.prepend(QLatin1String("com.trolltech.QtDBus.")); - } else if (interface.startsWith(QLatin1Char('Q')) && - interface.length() >= 2 && interface.at(1).isUpper()) { - // assume it's Qt - interface.prepend(QLatin1String("com.trolltech.Qt.")); - } else if (!QCoreApplication::instance()|| - QCoreApplication::instance()->applicationName().isEmpty()) { - interface.prepend(QLatin1String("local.")); - } else { - interface.prepend(QLatin1Char('.')).prepend(QCoreApplication::instance()->applicationName()); - QStringList domainName = - QCoreApplication::instance()->organizationDomain().split(QLatin1Char('.'), - QString::SkipEmptyParts); - if (domainName.isEmpty()) - interface.prepend(QLatin1String("local.")); - else - for (int i = 0; i < domainName.count(); ++i) - interface.prepend(QLatin1Char('.')).prepend(domainName.at(i)); - } - } - - return interface; - } - QString qDBusGenerateMetaObjectXml(QString interface, const QMetaObject *mo, const QMetaObject *base, int flags) { -- cgit v0.12 From 6bd18f891b4bbc265e5ddd18ba57095886b36e38 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 29 Jun 2009 15:32:26 +0200 Subject: Add some new error codes for indicating invalid D-Bus parameters. I'm wondering if I should be adding com.trolltech.QtDBus stuff now. But since there's already one there, I don't see why not... Reviewed-By: Harald Fernengel --- src/dbus/qdbuserror.cpp | 11 ++++++++++- src/dbus/qdbuserror.h | 6 +++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/dbus/qdbuserror.cpp b/src/dbus/qdbuserror.cpp index 817356d..7509ded 100644 --- a/src/dbus/qdbuserror.cpp +++ b/src/dbus/qdbuserror.cpp @@ -91,6 +91,10 @@ org.freedesktop.DBus.Error.InvalidSignature org.freedesktop.DBus.Error.UnknownInterface com.trolltech.QtDBus.Error.InternalError org.freedesktop.DBus.Error.UnknownObject +com.trolltech.QtDBus.Error.InvalidService +com.trolltech.QtDBus.Error.InvalidObjectPath +com.trolltech.QtDBus.Error.InvalidInterface +com.trolltech.QtDBus.Error.InvalidMember */ // in the same order as KnownErrors! @@ -116,12 +120,17 @@ static const char errorMessages_string[] = "org.freedesktop.DBus.Error.UnknownInterface\0" "com.trolltech.QtDBus.Error.InternalError\0" "org.freedesktop.DBus.Error.UnknownObject\0" + "com.trolltech.QtDBus.Error.InvalidService\0" + "com.trolltech.QtDBus.Error.InvalidObjectPath\0" + "com.trolltech.QtDBus.Error.InvalidInterface\0" + "com.trolltech.QtDBus.Error.InvalidMember\0" "\0"; static const int errorMessages_indices[] = { 0, 6, 40, 76, 118, 153, 191, 231, 273, 313, 349, 384, 421, 461, 501, 540, - 581, 617, 661, 705, 746, 0 + 581, 617, 661, 705, 746, 787, 829, 874, + 918, 0 }; static const int errorMessages_count = sizeof errorMessages_indices / diff --git a/src/dbus/qdbuserror.h b/src/dbus/qdbuserror.h index 7b77fd5..4e348dd 100644 --- a/src/dbus/qdbuserror.h +++ b/src/dbus/qdbuserror.h @@ -81,10 +81,14 @@ public: UnknownInterface, InternalError, UnknownObject, + InvalidService, + InvalidObjectPath, + InvalidInterface, + InvalidMember, #ifndef Q_QDOC // don't use this one! - LastErrorType = UnknownObject + LastErrorType = InvalidMember #endif }; -- cgit v0.12 From 96152ee50dfca7adf47b81b14015355260564a22 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 29 Jun 2009 17:52:33 +0200 Subject: Add central validation code to QDBusUtil. These tests are useful in QDBusMessage and QDBusAbstractInterface. It avoids having the same messages all over the place. Reviewed-By: Harald Fernengel --- src/dbus/qdbusutil_p.h | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/src/dbus/qdbusutil_p.h b/src/dbus/qdbusutil_p.h index 13031fd..5c1e4cd 100644 --- a/src/dbus/qdbusutil_p.h +++ b/src/dbus/qdbusutil_p.h @@ -57,6 +57,7 @@ #include #include +#include QT_BEGIN_HEADER @@ -83,6 +84,73 @@ namespace QDBusUtil QDBUS_EXPORT bool isValidSingleSignature(const QString &signature); QDBUS_EXPORT QString argumentToString(const QVariant &variant); + + enum AllowEmptyFlag { + EmptyAllowed, + EmptyNotAllowed + }; + + inline bool checkInterfaceName(const QString &name, AllowEmptyFlag empty, QDBusError *error) + { + if (name.isEmpty()) { + if (empty == EmptyAllowed) return true; + *error = QDBusError(QDBusError::InvalidInterface, QLatin1String("Interface name cannot be empty")); + return false; + } + if (isValidInterfaceName(name)) return true; + *error = QDBusError(QDBusError::InvalidInterface, QString::fromLatin1("Invalid interface class: %1").arg(name)); + return false; + } + + inline bool checkBusName(const QString &name, AllowEmptyFlag empty, QDBusError *error) + { + if (name.isEmpty()) { + if (empty == EmptyAllowed) return true; + *error = QDBusError(QDBusError::InvalidService, QLatin1String("Service name cannot be empty")); + return false; + } + if (isValidBusName(name)) return true; + *error = QDBusError(QDBusError::InvalidService, QString::fromLatin1("Invalid service name: %1").arg(name)); + return false; + } + + inline bool checkObjectPath(const QString &path, AllowEmptyFlag empty, QDBusError *error) + { + if (path.isEmpty()) { + if (empty == EmptyAllowed) return true; + *error = QDBusError(QDBusError::InvalidObjectPath, QLatin1String("Object path cannot be empty")); + return false; + } + if (isValidObjectPath(path)) return true; + *error = QDBusError(QDBusError::InvalidObjectPath, QString::fromLatin1("Invalid object path: %1").arg(path)); + return false; + } + + inline bool checkMemberName(const QString &name, AllowEmptyFlag empty, QDBusError *error, const char *nameType = 0) + { + if (!nameType) nameType = "member"; + if (name.isEmpty()) { + if (empty == EmptyAllowed) return true; + *error = QDBusError(QDBusError::InvalidMember, QLatin1String(nameType) + QLatin1String(" name cannot be empty")); + return false; + } + if (isValidMemberName(name)) return true; + *error = QDBusError(QDBusError::InvalidMember, QString::fromLatin1("Invalid %1 name: %2") + .arg(QString::fromLatin1(nameType), name)); + return false; + } + + inline bool checkErrorName(const QString &name, AllowEmptyFlag empty, QDBusError *error) + { + if (name.isEmpty()) { + if (empty == EmptyAllowed) return true; + *error = QDBusError(QDBusError::InvalidInterface, QLatin1String("Error name cannot be empty")); + return false; + } + if (isValidErrorName(name)) return true; + *error = QDBusError(QDBusError::InvalidInterface, QString::fromLatin1("Invalid error name: %1").arg(name)); + return false; + } } QT_END_NAMESPACE -- cgit v0.12 From bda9c20a556aa6ab6ccba978f7fc1ffe02c50813 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 29 Jun 2009 16:31:09 +0200 Subject: Add support for error messages in the D-Bus marshaller. Reviewed-By: Harald Fernengel --- src/dbus/qdbusargument_p.h | 3 ++- src/dbus/qdbusmarshaller.cpp | 35 ++++++++++++++++++++++------------- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/dbus/qdbusargument_p.h b/src/dbus/qdbusargument_p.h index b49a517..78bc683 100644 --- a/src/dbus/qdbusargument_p.h +++ b/src/dbus/qdbusargument_p.h @@ -130,7 +130,7 @@ public: QDBusMarshaller *endCommon(); void open(QDBusMarshaller &sub, int code, const char *signature); void close(); - void error(); + void error(const QString &message); bool appendVariantInternal(const QVariant &arg); bool appendRegisteredType(const QVariant &arg); @@ -140,6 +140,7 @@ public: DBusMessageIter iterator; QDBusMarshaller *parent; QByteArray *ba; + QString errorString; char closeCode; bool ok; diff --git a/src/dbus/qdbusmarshaller.cpp b/src/dbus/qdbusmarshaller.cpp index 7ada1ed..bb7fa6b 100644 --- a/src/dbus/qdbusmarshaller.cpp +++ b/src/dbus/qdbusmarshaller.cpp @@ -121,7 +121,7 @@ inline void QDBusMarshaller::append(const QDBusObjectPath &arg) { QByteArray data = arg.path().toUtf8(); if (!ba && data.isEmpty()) - error(); + error(QLatin1String("Invalid object path passed in arguments")); const char *cdata = data.constData(); qIterAppend(&iterator, ba, DBUS_TYPE_OBJECT_PATH, &cdata); } @@ -130,7 +130,7 @@ inline void QDBusMarshaller::append(const QDBusSignature &arg) { QByteArray data = arg.signature().toUtf8(); if (!ba && data.isEmpty()) - error(); + error(QLatin1String("Invalid signature passed in arguments")); const char *cdata = data.constData(); qIterAppend(&iterator, ba, DBUS_TYPE_SIGNATURE, &cdata); } @@ -161,7 +161,7 @@ inline bool QDBusMarshaller::append(const QDBusVariant &arg) QVariant::Type id = QVariant::Type(value.userType()); if (id == QVariant::Invalid) { qWarning("QDBusMarshaller: cannot add a null QDBusVariant"); - error(); + error(QLatin1String("Variant containing QVariant::Invalid passed in arguments")); return false; } @@ -180,7 +180,8 @@ inline bool QDBusMarshaller::append(const QDBusVariant &arg) qWarning("QDBusMarshaller: type `%s' (%d) is not registered with D-BUS. " "Use qDBusRegisterMetaType to register it", QVariant::typeToName( id ), id); - error(); + error(QString::fromLatin1("Unregistered type %1 passed in arguments") + .arg(QLatin1String(QVariant::typeToName(id)))); return false; } @@ -220,7 +221,8 @@ inline QDBusMarshaller *QDBusMarshaller::beginArray(int id) qWarning("QDBusMarshaller: type `%s' (%d) is not registered with D-BUS. " "Use qDBusRegisterMetaType to register it", QVariant::typeToName( QVariant::Type(id) ), id); - error(); + error(QString::fromLatin1("Unregistered type %1 passed in arguments") + .arg(QLatin1String(QVariant::typeToName(QVariant::Type(id))))); return this; } @@ -234,22 +236,26 @@ inline QDBusMarshaller *QDBusMarshaller::beginMap(int kid, int vid) qWarning("QDBusMarshaller: type `%s' (%d) is not registered with D-BUS. " "Use qDBusRegisterMetaType to register it", QVariant::typeToName( QVariant::Type(kid) ), kid); - error(); + error(QString::fromLatin1("Unregistered type %1 passed in arguments") + .arg(QLatin1String(QVariant::typeToName(QVariant::Type(kid))))); return this; } if (ksignature[1] != 0 || !q_dbus_type_is_basic(*ksignature)) { qWarning("QDBusMarshaller: type '%s' (%d) cannot be used as the key type in a D-BUS map.", QVariant::typeToName( QVariant::Type(kid) ), kid); - error(); + error(QString::fromLatin1("Type %1 passed in arguments cannot be used as a key in a map") + .arg(QLatin1String(QVariant::typeToName(QVariant::Type(kid))))); return this; } const char *vsignature = QDBusMetaType::typeToSignature( QVariant::Type(vid) ); if (!vsignature) { + const char *typeName = QVariant::typeToName(QVariant::Type(vid)); qWarning("QDBusMarshaller: type `%s' (%d) is not registered with D-BUS. " "Use qDBusRegisterMetaType to register it", - QVariant::typeToName( QVariant::Type(vid) ), vid); - error(); + typeName, vid); + error(QString::fromLatin1("Unregistered type %1 passed in arguments") + .arg(QLatin1String(typeName))); return this; } @@ -328,11 +334,13 @@ void QDBusMarshaller::close() } } -void QDBusMarshaller::error() +void QDBusMarshaller::error(const QString &msg) { ok = false; if (parent) - parent->error(); + parent->error(msg); + else + errorString = msg; } bool QDBusMarshaller::appendVariantInternal(const QVariant &arg) @@ -340,7 +348,7 @@ bool QDBusMarshaller::appendVariantInternal(const QVariant &arg) int id = arg.userType(); if (id == QVariant::Invalid) { qWarning("QDBusMarshaller: cannot add an invalid QVariant"); - error(); + error(QLatin1String("Variant containing QVariant::Invalid passed in arguments")); return false; } @@ -371,7 +379,8 @@ bool QDBusMarshaller::appendVariantInternal(const QVariant &arg) qWarning("QDBusMarshaller: type `%s' (%d) is not registered with D-BUS. " "Use qDBusRegisterMetaType to register it", QVariant::typeToName( QVariant::Type(id) ), id); - error(); + error(QString::fromLatin1("Unregistered type %1 passed in arguments") + .arg(QLatin1String(QVariant::typeToName(QVariant::Type(id))))); return false; } -- cgit v0.12 From 6b0b1a3eefe60dbeed3f56770fb58d487852e45b Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 30 Jun 2009 11:47:46 +0200 Subject: Adapt the message-sending code to return error messages from the marshalling code. Reviewed-By: Harald Fernengel --- src/dbus/qdbusintegrator.cpp | 89 +++++++++++++++----------- src/dbus/qdbusmessage.cpp | 48 ++++++++++---- src/dbus/qdbusmessage_p.h | 2 +- tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp | 16 ++++- 4 files changed, 104 insertions(+), 51 deletions(-) diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index 76179c9..704d2e3 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -1144,9 +1144,12 @@ void QDBusConnectionPrivate::relaySignal(QObject *obj, const QMetaObject *mo, in QDBusMessage message = QDBusMessage::createSignal(QLatin1String("/"), interface, QLatin1String(memberName)); message.setArguments(args); - DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message); + QDBusError error; + DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message, &error); if (!msg) { - qWarning("QDBusConnection: Could not emit signal %s.%s", qPrintable(interface), memberName.constData()); + qWarning("QDBusConnection: Could not emit signal %s.%s: %s", qPrintable(interface), memberName.constData(), + qPrintable(error.message())); + lastError = error; return; } @@ -1698,21 +1701,26 @@ int QDBusConnectionPrivate::send(const QDBusMessage& message) return -1; // don't send; the reply will be retrieved by the caller // through the d_ptr->localReply link - DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message); + QDBusError error; + DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message, &error); if (!msg) { if (message.type() == QDBusMessage::MethodCallMessage) - qWarning("QDBusConnection: error: could not send message to service \"%s\" path \"%s\" interface \"%s\" member \"%s\"", + qWarning("QDBusConnection: error: could not send message to service \"%s\" path \"%s\" interface \"%s\" member \"%s\": %s", qPrintable(message.service()), qPrintable(message.path()), - qPrintable(message.interface()), qPrintable(message.member())); + qPrintable(message.interface()), qPrintable(message.member()), + qPrintable(error.message())); else if (message.type() == QDBusMessage::SignalMessage) - qWarning("QDBusConnection: error: could not send signal path \"%s\" interface \"%s\" member \"%s\"", + qWarning("QDBusConnection: error: could not send signal path \"%s\" interface \"%s\" member \"%s\": %s", qPrintable(message.path()), qPrintable(message.interface()), - qPrintable(message.member())); + qPrintable(message.member()), + qPrintable(error.message())); else - qWarning("QDBusConnection: error: could not send %s message to service \"%s\"", + qWarning("QDBusConnection: error: could not send %s message to service \"%s\": %s", message.type() == QDBusMessage::ReplyMessage ? "reply" : message.type() == QDBusMessage::ErrorMessage ? "error" : - "invalid", qPrintable(message.service())); + "invalid", qPrintable(message.service()), + qPrintable(error.message())); + lastError = error; return 0; } @@ -1739,12 +1747,15 @@ QDBusMessage QDBusConnectionPrivate::sendWithReply(const QDBusMessage &message, return sendWithReplyLocal(message); if (!QCoreApplication::instance() || sendMode == QDBus::Block) { - DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message); + QDBusError err; + DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message, &err); if (!msg) { - qWarning("QDBusConnection: error: could not send message to service \"%s\" path \"%s\" interface \"%s\" member \"%s\"", + qWarning("QDBusConnection: error: could not send message to service \"%s\" path \"%s\" interface \"%s\" member \"%s\": %s", qPrintable(message.service()), qPrintable(message.path()), - qPrintable(message.interface()), qPrintable(message.member())); - return QDBusMessage(); + qPrintable(message.interface()), qPrintable(message.member()), + qPrintable(err.message())); + lastError = err; + return QDBusMessage::createError(err); } qDBusDebug() << QThread::currentThread() << "sending message (blocking):" << message; @@ -1754,9 +1765,8 @@ QDBusMessage QDBusConnectionPrivate::sendWithReply(const QDBusMessage &message, q_dbus_message_unref(msg); if (!!error) { - QDBusError qe = error; - lastError = qe; - return QDBusMessage::createError(qe); + lastError = err = error; + return QDBusMessage::createError(err); } QDBusMessage amsg = QDBusMessagePrivate::fromDBusMessage(reply); @@ -1766,16 +1776,17 @@ QDBusMessage QDBusConnectionPrivate::sendWithReply(const QDBusMessage &message, return amsg; } else { // use the event loop QDBusPendingCallPrivate *pcall = sendWithReplyAsync(message, timeout); - if (!pcall) - return QDBusMessage(); + Q_ASSERT(pcall); - pcall->watcherHelper = new QDBusPendingCallWatcherHelper; - QEventLoop loop; - loop.connect(pcall->watcherHelper, SIGNAL(reply(QDBusMessage)), SLOT(quit())); - loop.connect(pcall->watcherHelper, SIGNAL(error(QDBusError,QDBusMessage)), SLOT(quit())); + if (pcall->replyMessage.type() != QDBusMessage::InvalidMessage) { + pcall->watcherHelper = new QDBusPendingCallWatcherHelper; + QEventLoop loop; + loop.connect(pcall->watcherHelper, SIGNAL(reply(QDBusMessage)), SLOT(quit())); + loop.connect(pcall->watcherHelper, SIGNAL(error(QDBusError,QDBusMessage)), SLOT(quit())); - // enter the event loop and wait for a reply - loop.exec(QEventLoop::ExcludeUserInputEvents | QEventLoop::WaitForMoreEvents); + // enter the event loop and wait for a reply + loop.exec(QEventLoop::ExcludeUserInputEvents | QEventLoop::WaitForMoreEvents); + } QDBusMessage reply = pcall->replyMessage; lastError = reply; // set or clear error @@ -1831,20 +1842,25 @@ QDBusPendingCallPrivate *QDBusConnectionPrivate::sendWithReplyAsync(const QDBusM return pcall; } - DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message); + checkThread(); + QDBusPendingCallPrivate *pcall = new QDBusPendingCallPrivate; + pcall->sentMessage = message; + pcall->ref = 0; + + QDBusError error; + DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message, &error); if (!msg) { - qWarning("QDBusConnection: error: could not send message to service \"%s\" path \"%s\" interface \"%s\" member \"%s\"", + qWarning("QDBusConnection: error: could not send message to service \"%s\" path \"%s\" interface \"%s\" member \"%s\": %s", qPrintable(message.service()), qPrintable(message.path()), - qPrintable(message.interface()), qPrintable(message.member())); - return 0; + qPrintable(message.interface()), qPrintable(message.member()), + qPrintable(error.message())); + pcall->replyMessage = QDBusMessage::createError(error); + lastError = error; + return pcall; } - checkThread(); qDBusDebug() << QThread::currentThread() << "sending message (async):" << message; DBusPendingCall *pending = 0; - QDBusPendingCallPrivate *pcall = new QDBusPendingCallPrivate; - pcall->sentMessage = message; - pcall->ref = 0; QDBusDispatchLocker locker(SendWithReplyAsyncAction, this); if (q_dbus_connection_send_with_reply(connection, msg, &pending, timeout)) { @@ -1858,14 +1874,14 @@ QDBusPendingCallPrivate *QDBusConnectionPrivate::sendWithReplyAsync(const QDBusM return pcall; } else { // we're probably disconnected at this point - lastError = QDBusError(QDBusError::Disconnected, QLatin1String("Not connected to server")); + lastError = error = QDBusError(QDBusError::Disconnected, QLatin1String("Not connected to server")); } } else { - lastError = QDBusError(QDBusError::NoMemory, QLatin1String("Out of memory")); + lastError = error = QDBusError(QDBusError::NoMemory, QLatin1String("Out of memory")); } q_dbus_message_unref(msg); - pcall->replyMessage = QDBusMessage::createError(lastError); + pcall->replyMessage = QDBusMessage::createError(error); return pcall; } @@ -1874,8 +1890,7 @@ int QDBusConnectionPrivate::sendWithReplyAsync(const QDBusMessage &message, QObj int timeout) { QDBusPendingCallPrivate *pcall = sendWithReplyAsync(message, timeout); - if (!pcall) - return 0; + Q_ASSERT(pcall); // has it already finished (dispatched locally)? if (pcall->replyMessage.type() == QDBusMessage::ReplyMessage) { diff --git a/src/dbus/qdbusmessage.cpp b/src/dbus/qdbusmessage.cpp index 9150295..eb09de9 100644 --- a/src/dbus/qdbusmessage.cpp +++ b/src/dbus/qdbusmessage.cpp @@ -94,11 +94,17 @@ QString QDBusMessage::errorMessage() const \internal Constructs a DBusMessage object from this object. The returned value must be de-referenced with q_dbus_message_unref. + + The \a error object is set to indicate the error if anything went wrong with the + marshalling. Usually, this error message will be placed in the reply, as if the call failed. + The \a error pointer must not be null. */ -DBusMessage *QDBusMessagePrivate::toDBusMessage(const QDBusMessage &message) +DBusMessage *QDBusMessagePrivate::toDBusMessage(const QDBusMessage &message, QDBusError *error) { - if (!qdbus_loadLibDBus()) + if (!qdbus_loadLibDBus()) { + *error = QDBusError(QDBusError::Failed, QLatin1String("Could not open lidbus-1 library")); return 0; + } DBusMessage *msg = 0; const QDBusMessagePrivate *d_ptr = message.d_ptr; @@ -108,10 +114,17 @@ DBusMessage *QDBusMessagePrivate::toDBusMessage(const QDBusMessage &message) //qDebug() << "QDBusMessagePrivate::toDBusMessage" << "message is invalid"; break; case DBUS_MESSAGE_TYPE_METHOD_CALL: - // only interface can be empty - if (d_ptr->service.isEmpty() || d_ptr->path.isEmpty() || d_ptr->name.isEmpty()) - break; - msg = q_dbus_message_new_method_call(d_ptr->service.toUtf8(), d_ptr->path.toUtf8(), + // only service and interface can be empty -> path and name must not be empty + if (!QDBusUtil::checkBusName(d_ptr->service, QDBusUtil::EmptyAllowed, error)) + return 0; + if (!QDBusUtil::checkObjectPath(d_ptr->path, QDBusUtil::EmptyNotAllowed, error)) + return 0; + if (!QDBusUtil::checkInterfaceName(d_ptr->interface, QDBusUtil::EmptyAllowed, error)) + return 0; + if (!QDBusUtil::checkMemberName(d_ptr->name, QDBusUtil::EmptyNotAllowed, error, "method")) + return 0; + + msg = q_dbus_message_new_method_call(data(d_ptr->service.toUtf8()), d_ptr->path.toUtf8(), data(d_ptr->interface.toUtf8()), d_ptr->name.toUtf8()); break; case DBUS_MESSAGE_TYPE_METHOD_RETURN: @@ -123,8 +136,9 @@ DBusMessage *QDBusMessagePrivate::toDBusMessage(const QDBusMessage &message) break; case DBUS_MESSAGE_TYPE_ERROR: // error name can't be empty - if (d_ptr->name.isEmpty()) - break; + if (!QDBusUtil::checkErrorName(d_ptr->name, QDBusUtil::EmptyNotAllowed, error)) + return 0; + msg = q_dbus_message_new(DBUS_MESSAGE_TYPE_ERROR); q_dbus_message_set_error_name(msg, d_ptr->name.toUtf8()); if (!d_ptr->localMessage) { @@ -134,8 +148,13 @@ DBusMessage *QDBusMessagePrivate::toDBusMessage(const QDBusMessage &message) break; case DBUS_MESSAGE_TYPE_SIGNAL: // nothing can be empty here - if (d_ptr->path.isEmpty() || d_ptr->interface.isEmpty() || d_ptr->name.isEmpty()) - break; + if (!QDBusUtil::checkObjectPath(d_ptr->path, QDBusUtil::EmptyNotAllowed, error)) + return 0; + if (!QDBusUtil::checkInterfaceName(d_ptr->interface, QDBusUtil::EmptyAllowed, error)) + return 0; + if (!QDBusUtil::checkMemberName(d_ptr->name, QDBusUtil::EmptyNotAllowed, error, "method")) + return 0; + msg = q_dbus_message_new_signal(d_ptr->path.toUtf8(), d_ptr->interface.toUtf8(), d_ptr->name.toUtf8()); break; @@ -170,6 +189,7 @@ DBusMessage *QDBusMessagePrivate::toDBusMessage(const QDBusMessage &message) // not ok; q_dbus_message_unref(msg); + *error = QDBusError(QDBusError::Failed, QLatin1String("Marshalling failed: ") + marshaller.errorString); return 0; } @@ -247,7 +267,13 @@ QDBusMessage QDBusMessagePrivate::makeLocal(const QDBusConnectionPrivate &conn, // yes, we are // we must marshall and demarshall again so as to create QDBusArgument // entries for the complex types - DBusMessage *message = toDBusMessage(asSent); + QDBusError error; + DBusMessage *message = toDBusMessage(asSent, &error); + if (!message) { + // failed to marshall, so it's a call error + return QDBusMessage::createError(error); + } + q_dbus_message_set_sender(message, conn.baseService.toUtf8()); QDBusMessage retval = fromDBusMessage(message); diff --git a/src/dbus/qdbusmessage_p.h b/src/dbus/qdbusmessage_p.h index 12a9500..a0a681f 100644 --- a/src/dbus/qdbusmessage_p.h +++ b/src/dbus/qdbusmessage_p.h @@ -80,7 +80,7 @@ public: mutable uint delayedReply : 1; uint localMessage : 1; - static DBusMessage *toDBusMessage(const QDBusMessage &message); + static DBusMessage *toDBusMessage(const QDBusMessage &message, QDBusError *error); static QDBusMessage fromDBusMessage(DBusMessage *dmsg); static bool isLocal(const QDBusMessage &msg); diff --git a/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp b/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp index e5b2ebb..3ba789a 100644 --- a/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp +++ b/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp @@ -793,7 +793,7 @@ void tst_QDBusMarshall::sendErrors() "signalName"); msg << qVariantFromValue(QDBusObjectPath()); - QTest::ignoreMessage(QtWarningMsg, "QDBusConnection: error: could not send signal path \"/foo\" interface \"local.interfaceName\" member \"signalName\""); + QTest::ignoreMessage(QtWarningMsg, "QDBusConnection: error: could not send signal path \"/foo\" interface \"local.interfaceName\" member \"signalName\": Marshalling failed: Invalid object path passed in arguments"); QVERIFY(!con.send(msg)); msg.setArguments(QVariantList()); @@ -803,7 +803,19 @@ void tst_QDBusMarshall::sendErrors() path.setPath("abc"); msg << qVariantFromValue(path); - QTest::ignoreMessage(QtWarningMsg, "QDBusConnection: error: could not send signal path \"/foo\" interface \"local.interfaceName\" member \"signalName\""); + QTest::ignoreMessage(QtWarningMsg, "QDBusConnection: error: could not send signal path \"/foo\" interface \"local.interfaceName\" member \"signalName\": Marshalling failed: Invalid object path passed in arguments"); + QVERIFY(!con.send(msg)); + + QDBusSignature sig; + msg.setArguments(QVariantList() << qVariantFromValue(sig)); + QTest::ignoreMessage(QtWarningMsg, "QDBusConnection: error: could not send signal path \"/foo\" interface \"local.interfaceName\" member \"signalName\": Marshalling failed: Invalid signature passed in arguments"); + QVERIFY(!con.send(msg)); + + QTest::ignoreMessage(QtWarningMsg, "QDBusSignature: invalid signature \"a\""); + sig.setSignature("a"); + msg.setArguments(QVariantList()); + msg << qVariantFromValue(sig); + QTest::ignoreMessage(QtWarningMsg, "QDBusConnection: error: could not send signal path \"/foo\" interface \"local.interfaceName\" member \"signalName\": Marshalling failed: Invalid signature passed in arguments"); QVERIFY(!con.send(msg)); } -- cgit v0.12 From 8d4657764b0c4362dc25aa79a6e2853b8c98f0ad Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 29 Jun 2009 15:20:33 +0200 Subject: Keep creation failure errors for QDBusAbstractInterface. In case the object creation fails, set isValid to false. This will prevent any outgoing calls to be made with invalid information. In that case, lastError will never change either. This required adding a method to QDBusPendingCall, to be able to create one such object from an existing QDBusError. Reviewed-By: Marius Bugge Monsen --- src/dbus/qdbusabstractinterface.cpp | 140 ++++++++++++++++++------------------ src/dbus/qdbusabstractinterface_p.h | 4 ++ src/dbus/qdbuspendingcall.cpp | 36 ++++++++++ src/dbus/qdbuspendingcall.h | 3 + src/dbus/qdbuspendingcall_p.h | 3 + 5 files changed, 116 insertions(+), 70 deletions(-) diff --git a/src/dbus/qdbusabstractinterface.cpp b/src/dbus/qdbusabstractinterface.cpp index 85c3274..a4097c6 100644 --- a/src/dbus/qdbusabstractinterface.cpp +++ b/src/dbus/qdbusabstractinterface.cpp @@ -52,82 +52,66 @@ QT_BEGIN_NAMESPACE +static QDBusError checkIfValid(const QString &service, const QString &path, + const QString &interface, bool isDynamic) +{ + // We should be throwing exceptions here... oh well + QDBusError error; + + // dynamic interfaces (QDBusInterface) can have empty interfaces, but not service and object paths + // non-dynamic is the opposite: service and object paths can be empty, but not the interface + if (!isDynamic) { + // use assertion here because this should never happen, at all + Q_ASSERT_X(!interface.isEmpty(), "QDBusAbstractInterface", "Interface name cannot be empty"); + } + if (!QDBusUtil::checkBusName(service, isDynamic ? QDBusUtil::EmptyNotAllowed : QDBusUtil::EmptyAllowed, &error)) + return error; + if (!QDBusUtil::checkObjectPath(path, isDynamic ? QDBusUtil::EmptyNotAllowed : QDBusUtil::EmptyAllowed, &error)) + return error; + if (!QDBusUtil::checkInterfaceName(interface, QDBusUtil::EmptyAllowed, &error)) + return error; + + // no error + return QDBusError(); +} + QDBusAbstractInterfacePrivate::QDBusAbstractInterfacePrivate(const QString &serv, const QString &p, const QString &iface, const QDBusConnection& con, bool isDynamic) - : connection(con), service(serv), path(p), interface(iface), isValid(true) + : connection(con), service(serv), path(p), interface(iface), + lastError(checkIfValid(serv, p, iface, isDynamic)), + isValid(!lastError.isValid()) { - if (isDynamic) { - // QDBusInterface: service and object path can't be empty, but interface can -#if 0 - Q_ASSERT_X(QDBusUtil::isValidBusName(service), - "QDBusInterface::QDBusInterface", "Invalid service name"); - Q_ASSERT_X(QDBusUtil::isValidObjectPath(path), - "QDBusInterface::QDBusInterface", "Invalid object path given"); - Q_ASSERT_X(interface.isEmpty() || QDBusUtil::isValidInterfaceName(interface), - "QDBusInterface::QDBusInterface", "Invalid interface name"); -#else - if (!QDBusUtil::isValidBusName(service)) { - lastError = QDBusError(QDBusError::Disconnected, - QLatin1String("Invalid service name")); - isValid = false; - } else if (!QDBusUtil::isValidObjectPath(path)) { - lastError = QDBusError(QDBusError::Disconnected, - QLatin1String("Invalid object name given")); - isValid = false; - } else if (!interface.isEmpty() && !QDBusUtil::isValidInterfaceName(interface)) { - lastError = QDBusError(QDBusError::Disconnected, - QLatin1String("Invalid interface name")); - isValid = false; - } -#endif - } else { - // all others: service and path can be empty here, but interface can't -#if 0 - Q_ASSERT_X(service.isEmpty() || QDBusUtil::isValidBusName(service), - "QDBusAbstractInterface::QDBusAbstractInterface", "Invalid service name"); - Q_ASSERT_X(path.isEmpty() || QDBusUtil::isValidObjectPath(path), - "QDBusAbstractInterface::QDBusAbstractInterface", "Invalid object path given"); - Q_ASSERT_X(QDBusUtil::isValidInterfaceName(interface), - "QDBusAbstractInterface::QDBusAbstractInterface", "Invalid interface class!"); -#else - if (!service.isEmpty() && !QDBusUtil::isValidBusName(service)) { - lastError = QDBusError(QDBusError::Disconnected, - QLatin1String("Invalid service name")); - isValid = false; - } else if (!path.isEmpty() && !QDBusUtil::isValidObjectPath(path)) { - lastError = QDBusError(QDBusError::Disconnected, - QLatin1String("Invalid object path given")); - isValid = false; - } else if (!QDBusUtil::isValidInterfaceName(interface)) { - lastError = QDBusError(QDBusError::Disconnected, - QLatin1String("Invalid interface class")); - isValid = false; - } -#endif - } - if (!isValid) return; if (!connection.isConnected()) { lastError = QDBusError(QDBusError::Disconnected, QLatin1String("Not connected to D-Bus server")); - isValid = false; } else if (!service.isEmpty()) { currentOwner = connectionPrivate()->getNameOwner(service); // verify the name owner if (currentOwner.isEmpty()) { - isValid = false; lastError = connectionPrivate()->lastError; } } } +bool QDBusAbstractInterfacePrivate::canMakeCalls() const +{ + // recheck only if we have a wildcard (i.e. empty) service or path + // if any are empty, set the error message according to QDBusUtil + if (service.isEmpty()) + return QDBusUtil::checkBusName(service, QDBusUtil::EmptyNotAllowed, &lastError); + if (path.isEmpty()) + return QDBusUtil::checkObjectPath(path, QDBusUtil::EmptyNotAllowed, &lastError); + return true; +} + QVariant QDBusAbstractInterfacePrivate::property(const QMetaProperty &mp) const { - if (!connection.isConnected()) // not connected + if (!isValid || !canMakeCalls()) // can't make calls return QVariant(); // is this metatype registered? @@ -144,6 +128,9 @@ QVariant QDBusAbstractInterfacePrivate::property(const QMetaProperty &mp) const qWarning("QDBusAbstractInterface: type %s must be registered with QtDBus before it can be " "used to read property %s.%s", mp.typeName(), qPrintable(interface), mp.name()); + lastError = QDBusError(QDBusError::Failed, + QString::fromLatin1("Unregistered type %1 cannot be handled") + .arg(QLatin1String(mp.typeName()))); return QVariant(); } } @@ -208,7 +195,7 @@ QVariant QDBusAbstractInterfacePrivate::property(const QMetaProperty &mp) const void QDBusAbstractInterfacePrivate::setProperty(const QMetaProperty &mp, const QVariant &value) { - if (!connection.isConnected()) // not connected + if (!isValid || !canMakeCalls()) // can't make calls return; // send the value @@ -230,7 +217,6 @@ void QDBusAbstractInterfacePrivate::_q_serviceOwnerChanged(const QString &name, //qDebug() << "QDBusAbstractInterfacePrivate serviceOwnerChanged" << name << oldOwner << newOwner; if (name == service) { currentOwner = newOwner; - isValid = !newOwner.isEmpty(); } } @@ -261,7 +247,7 @@ QDBusAbstractInterface::QDBusAbstractInterface(QDBusAbstractInterfacePrivate &d, : QObject(d, parent) { // keep track of the service owner - if (d_func()->isValid) + if (!d_func()->currentOwner.isEmpty()) QObject::connect(d_func()->connectionPrivate(), SIGNAL(serviceOwnerChanged(QString,QString,QString)), this, SLOT(_q_serviceOwnerChanged(QString,QString,QString))); } @@ -300,7 +286,7 @@ QDBusAbstractInterface::~QDBusAbstractInterface() */ bool QDBusAbstractInterface::isValid() const { - return d_func()->isValid; + return !d_func()->currentOwner.isEmpty(); } /*! @@ -367,6 +353,9 @@ QDBusMessage QDBusAbstractInterface::callWithArgumentList(QDBus::CallMode mode, { Q_D(QDBusAbstractInterface); + if (!d->isValid || !d->canMakeCalls()) + return QDBusMessage::createError(d->lastError); + QString m = method; // split out the signature from the method int pos = method.indexOf(QLatin1Char('.')); @@ -425,6 +414,9 @@ QDBusPendingCall QDBusAbstractInterface::asyncCallWithArgumentList(const QString { Q_D(QDBusAbstractInterface); + if (!d->isValid || !d->canMakeCalls()) + return QDBusPendingCall::fromError(d->lastError); + QDBusMessage msg = QDBusMessage::createMethodCall(service(), path(), interface(), method); msg.setArguments(args); return d->connection.asyncCall(msg); @@ -440,7 +432,8 @@ QDBusPendingCall QDBusAbstractInterface::asyncCallWithArgumentList(const QString This function returns true if the queueing succeeds. It does not indicate that the executed call succeeded. If it fails, - the \a errorMethod is called. + the \a errorMethod is called. If the queueing failed, this + function returns false and no slot will be called. The \a returnMethod must have as its parameters the types returned by the function call. Optionally, it may have a QDBusMessage @@ -453,22 +446,25 @@ QDBusPendingCall QDBusAbstractInterface::asyncCallWithArgumentList(const QString bool QDBusAbstractInterface::callWithCallback(const QString &method, const QList &args, QObject *receiver, - const char *returnMethod, + const char *returnMethod, const char *errorMethod) { Q_D(QDBusAbstractInterface); + if (!d->isValid || !d->canMakeCalls()) + return false; + QDBusMessage msg = QDBusMessage::createMethodCall(service(), - path(), - interface(), - method); + path(), + interface(), + method); msg.setArguments(args); d->lastError = 0; return d->connection.callWithCallback(msg, - receiver, - returnMethod, - errorMethod); + receiver, + returnMethod, + errorMethod); } /*! @@ -492,7 +488,7 @@ bool QDBusAbstractInterface::callWithCallback(const QString &method, bool QDBusAbstractInterface::callWithCallback(const QString &method, const QList &args, QObject *receiver, - const char *slot) + const char *slot) { return callWithCallback(method, args, receiver, slot, 0); } @@ -503,13 +499,15 @@ bool QDBusAbstractInterface::callWithCallback(const QString &method, */ void QDBusAbstractInterface::connectNotify(const char *signal) { + // someone connecting to one of our signals + Q_D(QDBusAbstractInterface); + if (!d->isValid) + return; + // we end up recursing here, so optimise away if (qstrcmp(signal + 1, "destroyed(QObject*)") == 0) return; - // someone connecting to one of our signals - Q_D(QDBusAbstractInterface); - QDBusConnectionPrivate *conn = d->connectionPrivate(); if (conn) conn->connectRelay(d->service, d->currentOwner, d->path, d->interface, @@ -524,6 +522,8 @@ void QDBusAbstractInterface::disconnectNotify(const char *signal) { // someone disconnecting from one of our signals Q_D(QDBusAbstractInterface); + if (!d->isValid) + return; QDBusConnectionPrivate *conn = d->connectionPrivate(); if (conn) diff --git a/src/dbus/qdbusabstractinterface_p.h b/src/dbus/qdbusabstractinterface_p.h index e2ea058..e5822b3 100644 --- a/src/dbus/qdbusabstractinterface_p.h +++ b/src/dbus/qdbusabstractinterface_p.h @@ -75,11 +75,15 @@ public: QString path; QString interface; mutable QDBusError lastError; + + // this is set during creation and never changed + // it can't be const because QDBusInterfacePrivate has one more check bool isValid; QDBusAbstractInterfacePrivate(const QString &serv, const QString &p, const QString &iface, const QDBusConnection& con, bool dynamic); virtual ~QDBusAbstractInterfacePrivate() { } + bool canMakeCalls() const; // these functions do not check if the property is valid QVariant property(const QMetaProperty &mp) const; diff --git a/src/dbus/qdbuspendingcall.cpp b/src/dbus/qdbuspendingcall.cpp index 1797ed0..7807543 100644 --- a/src/dbus/qdbuspendingcall.cpp +++ b/src/dbus/qdbuspendingcall.cpp @@ -409,6 +409,42 @@ bool QDBusPendingCall::setReplyCallback(QObject *target, const char *member) } #endif +/*! + Creates a QDBusPendingCall object based on the error condition + \a error. The resulting pending call object will be in the + "finished" state and QDBusPendingReply::isError() will return true. + + \sa fromCompletedCall() +*/ +QDBusPendingCall QDBusPendingCall::fromError(const QDBusError &error) +{ + return fromCompletedCall(QDBusMessage::createError(error)); +} + +/*! + Creates a QDBusPendingCall object based on the message \a msg. + The message must be of type QDBusMessage::ErrorMessage or + QDBusMessage::ReplyMessage (that is, a message that is typical + of a completed call). + + This function is useful for code that requires simulating a pending + call, but that has already finished. + + \sa fromError() +*/ +QDBusPendingCall QDBusPendingCall::fromCompletedCall(const QDBusMessage &msg) +{ + QDBusPendingCallPrivate *d = 0; + if (msg.type() == QDBusMessage::ErrorMessage || + msg.type() == QDBusMessage::ReplyMessage) { + d = new QDBusPendingCallPrivate; + d->replyMessage = msg; + d->connection = 0; + } + + return QDBusPendingCall(d); +} + class QDBusPendingCallWatcherPrivate: public QObjectPrivate { diff --git a/src/dbus/qdbuspendingcall.h b/src/dbus/qdbuspendingcall.h index 8881920..8dbbb3c 100644 --- a/src/dbus/qdbuspendingcall.h +++ b/src/dbus/qdbuspendingcall.h @@ -78,6 +78,9 @@ public: QDBusMessage reply() const; #endif + static QDBusPendingCall fromError(const QDBusError &error); + static QDBusPendingCall fromCompletedCall(const QDBusMessage &message); + protected: QExplicitlySharedDataPointer d; friend class QDBusPendingCallPrivate; diff --git a/src/dbus/qdbuspendingcall_p.h b/src/dbus/qdbuspendingcall_p.h index 7136f67..5577451 100644 --- a/src/dbus/qdbuspendingcall_p.h +++ b/src/dbus/qdbuspendingcall_p.h @@ -63,6 +63,7 @@ QT_BEGIN_NAMESPACE +class QDBusPendingCall; class QDBusPendingCallWatcher; class QDBusPendingCallWatcherHelper; class QDBusConnectionPrivate; @@ -94,6 +95,8 @@ public: void waitForFinished(); void setMetaTypes(int count, const int *types); void checkReceivedSignature(); + + static QDBusPendingCall fromMessage(const QDBusMessage &msg); }; class QDBusPendingCallWatcherHelper: public QObject -- cgit v0.12 From e7ca74ed8a41eb4c05f436007417d160b6cf94f7 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 30 Jun 2009 11:13:47 +0200 Subject: Avoid revalidating message parameters. This is a small performance improvement when making a call: we don't need to validate what we already know to be valid because we either designed it to be so or because we've already validated. The D-Bus library unfortunately validates again and there's nothing we can do about it. But we can avoid doing it twice in our own code. Reviewed-By: Marius Bugge Monsen --- src/dbus/qdbusabstractinterface.cpp | 6 ++++ src/dbus/qdbusintegrator.cpp | 3 ++ src/dbus/qdbusinternalfilters.cpp | 2 +- src/dbus/qdbusmessage.cpp | 60 +++++++++++++++++++++---------------- src/dbus/qdbusmessage.h | 6 ++-- src/dbus/qdbusmessage_p.h | 9 ++++++ 6 files changed, 55 insertions(+), 31 deletions(-) diff --git a/src/dbus/qdbusabstractinterface.cpp b/src/dbus/qdbusabstractinterface.cpp index a4097c6..08da997 100644 --- a/src/dbus/qdbusabstractinterface.cpp +++ b/src/dbus/qdbusabstractinterface.cpp @@ -44,6 +44,7 @@ #include "qdbusargument.h" #include "qdbuspendingcall.h" +#include "qdbusmessage_p.h" #include "qdbusmetaobject_p.h" #include "qdbusmetatype_p.h" #include "qdbusutil_p.h" @@ -139,6 +140,7 @@ QVariant QDBusAbstractInterfacePrivate::property(const QMetaProperty &mp) const QDBusMessage msg = QDBusMessage::createMethodCall(service, path, QLatin1String(DBUS_INTERFACE_PROPERTIES), QLatin1String("Get")); + QDBusMessagePrivate::setParametersValidated(msg, true); msg << interface << QString::fromUtf8(mp.name()); QDBusMessage reply = connection.call(msg, QDBus::Block); @@ -202,6 +204,7 @@ void QDBusAbstractInterfacePrivate::setProperty(const QMetaProperty &mp, const Q QDBusMessage msg = QDBusMessage::createMethodCall(service, path, QLatin1String(DBUS_INTERFACE_PROPERTIES), QLatin1String("Set")); + QDBusMessagePrivate::setParametersValidated(msg, true); msg << interface << QString::fromUtf8(mp.name()) << qVariantFromValue(QDBusVariant(value)); QDBusMessage reply = connection.call(msg, QDBus::Block); @@ -386,6 +389,7 @@ QDBusMessage QDBusAbstractInterface::callWithArgumentList(QDBus::CallMode mode, // qDebug() << "QDBusAbstractInterface" << "Service" << service() << "Path:" << path(); QDBusMessage msg = QDBusMessage::createMethodCall(service(), path(), interface(), m); + QDBusMessagePrivate::setParametersValidated(msg, true); msg.setArguments(args); QDBusMessage reply = d->connection.call(msg, mode); @@ -418,6 +422,7 @@ QDBusPendingCall QDBusAbstractInterface::asyncCallWithArgumentList(const QString return QDBusPendingCall::fromError(d->lastError); QDBusMessage msg = QDBusMessage::createMethodCall(service(), path(), interface(), method); + QDBusMessagePrivate::setParametersValidated(msg, true); msg.setArguments(args); return d->connection.asyncCall(msg); } @@ -458,6 +463,7 @@ bool QDBusAbstractInterface::callWithCallback(const QString &method, path(), interface(), method); + QDBusMessagePrivate::setParametersValidated(msg, true); msg.setArguments(args); d->lastError = 0; diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index 704d2e3..a0903ed 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -1143,6 +1143,7 @@ void QDBusConnectionPrivate::relaySignal(QObject *obj, const QMetaObject *mo, in QDBusReadLocker locker(RelaySignalAction, this); QDBusMessage message = QDBusMessage::createSignal(QLatin1String("/"), interface, QLatin1String(memberName)); + QDBusMessagePrivate::setParametersValidated(message, true); message.setArguments(args); QDBusError error; DBusMessage *msg = QDBusMessagePrivate::toDBusMessage(message, &error); @@ -2092,6 +2093,7 @@ QString QDBusConnectionPrivate::getNameOwner(const QString& serviceName) QDBusMessage msg = QDBusMessage::createMethodCall(QLatin1String(DBUS_SERVICE_DBUS), QLatin1String(DBUS_PATH_DBUS), QLatin1String(DBUS_INTERFACE_DBUS), QLatin1String("GetNameOwner")); + QDBusMessagePrivate::setParametersValidated(msg, true); msg << serviceName; QDBusMessage reply = sendWithReply(msg, QDBus::Block); if (reply.type() == QDBusMessage::ReplyMessage) @@ -2115,6 +2117,7 @@ QDBusConnectionPrivate::findMetaObject(const QString &service, const QString &pa QDBusMessage msg = QDBusMessage::createMethodCall(service, path, QLatin1String(DBUS_INTERFACE_INTROSPECTABLE), QLatin1String("Introspect")); + QDBusMessagePrivate::setParametersValidated(msg, true); QDBusMessage reply = sendWithReply(msg, QDBus::Block); diff --git a/src/dbus/qdbusinternalfilters.cpp b/src/dbus/qdbusinternalfilters.cpp index 416144d..762a49b 100644 --- a/src/dbus/qdbusinternalfilters.cpp +++ b/src/dbus/qdbusinternalfilters.cpp @@ -179,7 +179,7 @@ QString qDBusIntrospectObject(const QDBusConnectionPrivate::ObjectTreeNode &node static QDBusMessage qDBusPropertyError(const QDBusMessage &msg, const QString &interface_name) { - return msg.createErrorReply(QLatin1String(DBUS_ERROR_INVALID_ARGS), + return msg.createErrorReply(QDBusError::InvalidArgs, QString::fromLatin1("Interface %1 was not found in object %2") .arg(interface_name) .arg(msg.path())); diff --git a/src/dbus/qdbusmessage.cpp b/src/dbus/qdbusmessage.cpp index eb09de9..78de6d9 100644 --- a/src/dbus/qdbusmessage.cpp +++ b/src/dbus/qdbusmessage.cpp @@ -62,7 +62,8 @@ static inline const char *data(const QByteArray &arr) QDBusMessagePrivate::QDBusMessagePrivate() : msg(0), reply(0), type(DBUS_MESSAGE_TYPE_INVALID), - timeout(-1), localReply(0), ref(1), delayedReply(false), localMessage(false) + timeout(-1), localReply(0), ref(1), delayedReply(false), localMessage(false), + parametersValidated(false) { } @@ -115,14 +116,16 @@ DBusMessage *QDBusMessagePrivate::toDBusMessage(const QDBusMessage &message, QDB break; case DBUS_MESSAGE_TYPE_METHOD_CALL: // only service and interface can be empty -> path and name must not be empty - if (!QDBusUtil::checkBusName(d_ptr->service, QDBusUtil::EmptyAllowed, error)) - return 0; - if (!QDBusUtil::checkObjectPath(d_ptr->path, QDBusUtil::EmptyNotAllowed, error)) - return 0; - if (!QDBusUtil::checkInterfaceName(d_ptr->interface, QDBusUtil::EmptyAllowed, error)) - return 0; - if (!QDBusUtil::checkMemberName(d_ptr->name, QDBusUtil::EmptyNotAllowed, error, "method")) - return 0; + if (!d_ptr->parametersValidated) { + if (!QDBusUtil::checkBusName(d_ptr->service, QDBusUtil::EmptyAllowed, error)) + return 0; + if (!QDBusUtil::checkObjectPath(d_ptr->path, QDBusUtil::EmptyNotAllowed, error)) + return 0; + if (!QDBusUtil::checkInterfaceName(d_ptr->interface, QDBusUtil::EmptyAllowed, error)) + return 0; + if (!QDBusUtil::checkMemberName(d_ptr->name, QDBusUtil::EmptyNotAllowed, error, "method")) + return 0; + } msg = q_dbus_message_new_method_call(data(d_ptr->service.toUtf8()), d_ptr->path.toUtf8(), data(d_ptr->interface.toUtf8()), d_ptr->name.toUtf8()); @@ -136,7 +139,8 @@ DBusMessage *QDBusMessagePrivate::toDBusMessage(const QDBusMessage &message, QDB break; case DBUS_MESSAGE_TYPE_ERROR: // error name can't be empty - if (!QDBusUtil::checkErrorName(d_ptr->name, QDBusUtil::EmptyNotAllowed, error)) + if (!d_ptr->parametersValidated + && !QDBusUtil::checkErrorName(d_ptr->name, QDBusUtil::EmptyNotAllowed, error)) return 0; msg = q_dbus_message_new(DBUS_MESSAGE_TYPE_ERROR); @@ -148,12 +152,14 @@ DBusMessage *QDBusMessagePrivate::toDBusMessage(const QDBusMessage &message, QDB break; case DBUS_MESSAGE_TYPE_SIGNAL: // nothing can be empty here - if (!QDBusUtil::checkObjectPath(d_ptr->path, QDBusUtil::EmptyNotAllowed, error)) - return 0; - if (!QDBusUtil::checkInterfaceName(d_ptr->interface, QDBusUtil::EmptyAllowed, error)) - return 0; - if (!QDBusUtil::checkMemberName(d_ptr->name, QDBusUtil::EmptyNotAllowed, error, "method")) - return 0; + if (!d_ptr->parametersValidated) { + if (!QDBusUtil::checkObjectPath(d_ptr->path, QDBusUtil::EmptyNotAllowed, error)) + return 0; + if (!QDBusUtil::checkInterfaceName(d_ptr->interface, QDBusUtil::EmptyAllowed, error)) + return 0; + if (!QDBusUtil::checkMemberName(d_ptr->name, QDBusUtil::EmptyNotAllowed, error, "method")) + return 0; + } msg = q_dbus_message_new_signal(d_ptr->path.toUtf8(), d_ptr->interface.toUtf8(), d_ptr->name.toUtf8()); @@ -162,16 +168,11 @@ DBusMessage *QDBusMessagePrivate::toDBusMessage(const QDBusMessage &message, QDB Q_ASSERT(false); break; } -#if 0 - DBusError err; - q_dbus_error_init(&err); - if (q_dbus_error_is_set(&err)) { - QDBusError qe(&err); - qDebug() << "QDBusMessagePrivate::toDBusMessage" << qe; - } -#endif - if (!msg) - return 0; + + // if we got here, the parameters validated + // and since the message parameters cannot be changed once the message is created + // we can record this fact + d_ptr->parametersValidated = true; QDBusMarshaller marshaller; QVariantList::ConstIterator it = d_ptr->arguments.constBegin(); @@ -492,6 +493,13 @@ QDBusMessage QDBusMessage::createErrorReply(const QString name, const QString &m Constructs a new DBus reply message for the error type \a type using the message \a msg. Returns the DBus message. */ +QDBusMessage QDBusMessage::createErrorReply(QDBusError::ErrorType atype, const QString &amsg) const +{ + QDBusMessage msg = createErrorReply(QDBusError::errorString(atype), amsg); + msg.d_ptr->parametersValidated = true; + return msg; +} + /*! Constructs an empty, invalid QDBusMessage object. diff --git a/src/dbus/qdbusmessage.h b/src/dbus/qdbusmessage.h index 55f388a..34b1635 100644 --- a/src/dbus/qdbusmessage.h +++ b/src/dbus/qdbusmessage.h @@ -87,8 +87,9 @@ public: QDBusMessage createErrorReply(const QString name, const QString &msg) const; inline QDBusMessage createErrorReply(const QDBusError &err) const { return createErrorReply(err.name(), err.message()); } - inline QDBusMessage createErrorReply(QDBusError::ErrorType type, const QString &msg) const; + QDBusMessage createErrorReply(QDBusError::ErrorType type, const QString &msg) const; + // there are no setters; if this changes, see qdbusmessage_p.h QString service() const; QString path() const; QString interface() const; @@ -113,9 +114,6 @@ private: QDBusMessagePrivate *d_ptr; }; -inline QDBusMessage QDBusMessage::createErrorReply(QDBusError::ErrorType atype, const QString &amsg) const -{ return createErrorReply(QDBusError::errorString(atype), amsg); } - #ifndef QT_NO_DEBUG_STREAM QDBUS_EXPORT QDebug operator<<(QDebug, const QDBusMessage &); #endif diff --git a/src/dbus/qdbusmessage_p.h b/src/dbus/qdbusmessage_p.h index a0a681f..b8f23dc 100644 --- a/src/dbus/qdbusmessage_p.h +++ b/src/dbus/qdbusmessage_p.h @@ -55,6 +55,7 @@ #include #include +#include struct DBusMessage; @@ -69,7 +70,11 @@ public: ~QDBusMessagePrivate(); QList arguments; + + // the following parameters are "const": they are not changed after the constructors + // the parametersValidated member below controls whether they've been validated already QString service, path, interface, name, message, signature; + DBusMessage *msg; DBusMessage *reply; int type; @@ -79,6 +84,10 @@ public: mutable uint delayedReply : 1; uint localMessage : 1; + mutable uint parametersValidated : 1; + + static void setParametersValidated(QDBusMessage &msg, bool enable) + { msg.d_ptr->parametersValidated = enable; } static DBusMessage *toDBusMessage(const QDBusMessage &message, QDBusError *error); static QDBusMessage fromDBusMessage(DBusMessage *dmsg); -- cgit v0.12 From 485b2afb790444a0c6c2b32fbac65421e652dbe4 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 30 Jun 2009 18:27:11 +0200 Subject: Use an "int status" extra parameter in property reading/writing. When calling qt_metacall with the ReadProperty or WriteProperty, the data is on argv[0] like it was before, but now the QVariant itself is on argv[1] and there's an extra parameter in argv[2] which the meta code can use to indicate result. This allows QtDBus to process properties much more easily. In the case of property reading, we need to be able to modify the variant itself, because copying types when we don't have the data isn't very easy. As for setting, we need to be able to tell setProperty to return true or false depending on whether we succeeded in setting the property or not. Reviewed-By: Kent Hansen Reviewed-By: Marius Bugge Monsen --- src/corelib/kernel/qmetaobject.cpp | 23 ++++++++++++++++----- src/dbus/qdbusabstractinterface.cpp | 40 ++++++++++++++++++++++++++++++++----- src/dbus/qdbusabstractinterface.h | 18 ++++++++++++++++- src/dbus/qdbusabstractinterface_p.h | 2 +- src/dbus/qdbusinterface.cpp | 20 ------------------- 5 files changed, 71 insertions(+), 32 deletions(-) diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 71dd5ff..34f580b 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -2131,8 +2131,15 @@ QVariant QMetaProperty::read(const QObject *object) const return QVariant(); } } + + // the status variable is changed by qt_metacall to indicate what it did + // this feature is currently only used by QtDBus and should not be depended + // upon. Don't change it without looking into QDBusAbstractInterface first + // -1 (unchanged): normal qt_metacall, result stored in argv[0] + // changed: result stored directly in value + int status = -1; QVariant value; - void *argv[2] = { 0, &value }; + void *argv[] = { 0, &value, &status }; if (t == QVariant::LastType) { argv[0] = &value; } else { @@ -2142,8 +2149,8 @@ QVariant QMetaProperty::read(const QObject *object) const const_cast(object)->qt_metacall(QMetaObject::ReadProperty, idx + mobj->propertyOffset(), argv); - if (argv[1] == 0) - // "value" was changed + + if (status != -1) return value; if (t != QVariant::LastType && argv[0] != value.data()) // pointer or reference @@ -2201,13 +2208,19 @@ bool QMetaProperty::write(QObject *object, const QVariant &value) const return false; } - void *argv[2] = { 0, &v }; + // the status variable is changed by qt_metacall to indicate what it did + // this feature is currently only used by QtDBus and should not be depended + // upon. Don't change it without looking into QDBusAbstractInterface first + // -1 (unchanged): normal qt_metacall, result stored in argv[0] + // changed: result stored directly in value, return the value of status + int status = -1; + void *argv[] = { 0, &v, &status }; if (t == QVariant::LastType) argv[0] = &v; else argv[0] = v.data(); object->qt_metacall(QMetaObject::WriteProperty, idx + mobj->propertyOffset(), argv); - return true; + return status; } /*! diff --git a/src/dbus/qdbusabstractinterface.cpp b/src/dbus/qdbusabstractinterface.cpp index 08da997..9bef2dd 100644 --- a/src/dbus/qdbusabstractinterface.cpp +++ b/src/dbus/qdbusabstractinterface.cpp @@ -195,10 +195,10 @@ QVariant QDBusAbstractInterfacePrivate::property(const QMetaProperty &mp) const return QVariant(); } -void QDBusAbstractInterfacePrivate::setProperty(const QMetaProperty &mp, const QVariant &value) +bool QDBusAbstractInterfacePrivate::setProperty(const QMetaProperty &mp, const QVariant &value) { if (!isValid || !canMakeCalls()) // can't make calls - return; + return false; // send the value QDBusMessage msg = QDBusMessage::createMethodCall(service, path, @@ -208,8 +208,11 @@ void QDBusAbstractInterfacePrivate::setProperty(const QMetaProperty &mp, const Q msg << interface << QString::fromUtf8(mp.name()) << qVariantFromValue(QDBusVariant(value)); QDBusMessage reply = connection.call(msg, QDBus::Block); - if (reply.type() != QDBusMessage::ReplyMessage) + if (reply.type() != QDBusMessage::ReplyMessage) { lastError = reply; + return false; + } + return true; } void QDBusAbstractInterfacePrivate::_q_serviceOwnerChanged(const QString &name, @@ -223,6 +226,33 @@ void QDBusAbstractInterfacePrivate::_q_serviceOwnerChanged(const QString &name, } } +QDBusAbstractInterfaceBase::QDBusAbstractInterfaceBase(QDBusAbstractInterfacePrivate &d, QObject *parent) + : QObject(d, parent) +{ +} + +int QDBusAbstractInterfaceBase::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + int saved_id = _id; + _id = QObject::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + + if (_c == QMetaObject::ReadProperty || _c == QMetaObject::WriteProperty) { + QMetaProperty mp = metaObject()->property(saved_id); + int &status = *reinterpret_cast(_a[2]); + QVariant &variant = *reinterpret_cast(_a[1]); + + if (_c == QMetaObject::WriteProperty) { + status = d_func()->setProperty(mp, variant) ? 1 : 0; + } else { + variant = d_func()->property(mp); + status = variant.isValid() ? 1 : 0; + } + _id = -1; + } + return _id; +} /*! \class QDBusAbstractInterface @@ -247,7 +277,7 @@ void QDBusAbstractInterfacePrivate::_q_serviceOwnerChanged(const QString &name, This is the constructor called from QDBusInterface::QDBusInterface. */ QDBusAbstractInterface::QDBusAbstractInterface(QDBusAbstractInterfacePrivate &d, QObject *parent) - : QObject(d, parent) + : QDBusAbstractInterfaceBase(d, parent) { // keep track of the service owner if (!d_func()->currentOwner.isEmpty()) @@ -263,7 +293,7 @@ QDBusAbstractInterface::QDBusAbstractInterface(QDBusAbstractInterfacePrivate &d, QDBusAbstractInterface::QDBusAbstractInterface(const QString &service, const QString &path, const char *interface, const QDBusConnection &con, QObject *parent) - : QObject(*new QDBusAbstractInterfacePrivate(service, path, QString::fromLatin1(interface), + : QDBusAbstractInterfaceBase(*new QDBusAbstractInterfacePrivate(service, path, QString::fromLatin1(interface), con, false), parent) { // keep track of the service owner diff --git a/src/dbus/qdbusabstractinterface.h b/src/dbus/qdbusabstractinterface.h index 6400b26..e525f77 100644 --- a/src/dbus/qdbusabstractinterface.h +++ b/src/dbus/qdbusabstractinterface.h @@ -61,7 +61,23 @@ class QDBusError; class QDBusPendingCall; class QDBusAbstractInterfacePrivate; -class QDBUS_EXPORT QDBusAbstractInterface: public QObject + +class QDBUS_EXPORT QDBusAbstractInterfaceBase: public QObject +{ +public: + int qt_metacall(QMetaObject::Call, int, void**); +protected: + QDBusAbstractInterfaceBase(QDBusAbstractInterfacePrivate &dd, QObject *parent); +private: + Q_DECLARE_PRIVATE(QDBusAbstractInterface) +}; + +class QDBUS_EXPORT QDBusAbstractInterface: +#ifdef Q_QDOC + public QObject +#else + public QDBusAbstractInterfaceBase +#endif { Q_OBJECT diff --git a/src/dbus/qdbusabstractinterface_p.h b/src/dbus/qdbusabstractinterface_p.h index e5822b3..e577898 100644 --- a/src/dbus/qdbusabstractinterface_p.h +++ b/src/dbus/qdbusabstractinterface_p.h @@ -87,7 +87,7 @@ public: // these functions do not check if the property is valid QVariant property(const QMetaProperty &mp) const; - void setProperty(const QMetaProperty &mp, const QVariant &value); + bool setProperty(const QMetaProperty &mp, const QVariant &value); // return conn's d pointer inline QDBusConnectionPrivate *connectionPrivate() const diff --git a/src/dbus/qdbusinterface.cpp b/src/dbus/qdbusinterface.cpp index 211b717..6f61847 100644 --- a/src/dbus/qdbusinterface.cpp +++ b/src/dbus/qdbusinterface.cpp @@ -205,26 +205,6 @@ int QDBusInterfacePrivate::metacall(QMetaObject::Call c, int id, void **argv) // done return -1; } - } else if (c == QMetaObject::ReadProperty) { - // Qt doesn't support non-readable properties - // we have to re-check - QMetaProperty mp = metaObject->property(id + metaObject->propertyOffset()); - if (!mp.isReadable()) - return -1; // don't read - - QVariant *value = reinterpret_cast(argv[1]); - argv[1] = 0; - *value = property(mp); - - return -1; // handled, error or not - } else if (c == QMetaObject::WriteProperty) { - // QMetaProperty::write has already checked that we're writable - // it has also checked that the type is right - QVariant *value = reinterpret_cast(argv[1]); - QMetaProperty mp = metaObject->property(id + metaObject->propertyOffset()); - - setProperty(mp, *value); - return -1; } return id; } -- cgit v0.12 From c4fa498f447bd569ee91e16f07bdb7954b5adc76 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 30 Jun 2009 20:52:35 +0200 Subject: Fix setting of complex/custom properties and error messages. Complex properties require demarshalling before passing on to QMetaProperty::write(). We can't pass on a QVariant containing an un-demarshalled QDBusArgument. So add a new function that does the decoding properly, as well as error checking. Also take the opportunity to properly check the interface name in the case of setting a property exported from the object itself (not an adaptor). Task-number: 240608 Reviewed-by: Marius Bugge Monsen --- src/dbus/qdbusinternalfilters.cpp | 167 +++++++++++++++++++++++++++++++------- 1 file changed, 136 insertions(+), 31 deletions(-) diff --git a/src/dbus/qdbusinternalfilters.cpp b/src/dbus/qdbusinternalfilters.cpp index 762a49b..45cbbb0 100644 --- a/src/dbus/qdbusinternalfilters.cpp +++ b/src/dbus/qdbusinternalfilters.cpp @@ -53,6 +53,7 @@ #include "qdbusextratypes.h" #include "qdbusmessage.h" #include "qdbusmetatype.h" +#include "qdbusmetatype_p.h" #include "qdbusmessage_p.h" #include "qdbusutil_p.h" @@ -177,14 +178,25 @@ QString qDBusIntrospectObject(const QDBusConnectionPrivate::ObjectTreeNode &node // implement the D-Bus interface org.freedesktop.DBus.Properties -static QDBusMessage qDBusPropertyError(const QDBusMessage &msg, const QString &interface_name) +static inline QDBusMessage interfaceNotFoundError(const QDBusMessage &msg, const QString &interface_name) { - return msg.createErrorReply(QDBusError::InvalidArgs, + return msg.createErrorReply(QDBusError::UnknownInterface, QString::fromLatin1("Interface %1 was not found in object %2") .arg(interface_name) .arg(msg.path())); } +static inline QDBusMessage +propertyNotFoundError(const QDBusMessage &msg, const QString &interface_name, const QByteArray &property_name) +{ + return msg.createErrorReply(QDBusError::InvalidArgs, + QString::fromLatin1("Property %1%2%3 was not found in object %4") + .arg(interface_name, + QString::fromLatin1(interface_name.isEmpty() ? "" : "."), + QString::fromLatin1(property_name), + msg.path())); +} + QDBusMessage qDBusPropertyGet(const QDBusConnectionPrivate::ObjectTreeNode &node, const QDBusMessage &msg) { @@ -198,6 +210,7 @@ QDBusMessage qDBusPropertyGet(const QDBusConnectionPrivate::ObjectTreeNode &node QDBusAdaptorConnector *connector; QVariant value; + bool interfaceFound = false; if (node.flags & QDBusConnection::ExportAdaptors && (connector = qDBusFindAdaptorConnector(node.obj))) { @@ -217,31 +230,122 @@ QDBusMessage qDBusPropertyGet(const QDBusConnectionPrivate::ObjectTreeNode &node QDBusAdaptorConnector::AdaptorMap::ConstIterator it; it = qLowerBound(connector->adaptors.constBegin(), connector->adaptors.constEnd(), interface_name); - if (it != connector->adaptors.constEnd() && interface_name == QLatin1String(it->interface)) + if (it != connector->adaptors.constEnd() && interface_name == QLatin1String(it->interface)) { + interfaceFound = true; value = it->adaptor->property(property_name); + } } } - if (!value.isValid() && node.flags & (QDBusConnection::ExportAllProperties | - QDBusConnection::ExportNonScriptableProperties)) { + if (!interfaceFound && !value.isValid() + && node.flags & (QDBusConnection::ExportAllProperties | + QDBusConnection::ExportNonScriptableProperties)) { // try the object itself - int pidx = node.obj->metaObject()->indexOfProperty(property_name); - if (pidx != -1) { - QMetaProperty mp = node.obj->metaObject()->property(pidx); - if ((mp.isScriptable() && (node.flags & QDBusConnection::ExportScriptableProperties)) || - (!mp.isScriptable() && (node.flags & QDBusConnection::ExportNonScriptableProperties))) - value = mp.read(node.obj); + if (!interface_name.isEmpty()) + interfaceFound = qDBusInterfaceInObject(node.obj, interface_name); + + if (interfaceFound) { + int pidx = node.obj->metaObject()->indexOfProperty(property_name); + if (pidx != -1) { + QMetaProperty mp = node.obj->metaObject()->property(pidx); + if ((mp.isScriptable() && (node.flags & QDBusConnection::ExportScriptableProperties)) || + (!mp.isScriptable() && (node.flags & QDBusConnection::ExportNonScriptableProperties))) + value = mp.read(node.obj); + } } } if (!value.isValid()) { // the property was not found - return qDBusPropertyError(msg, interface_name); + if (!interfaceFound) + return interfaceNotFoundError(msg, interface_name); + return propertyNotFoundError(msg, interface_name, property_name); } return msg.createReply(qVariantFromValue(QDBusVariant(value))); } +enum PropertyWriteResult { + PropertyWriteSuccess = 0, + PropertyNotFound, + PropertyTypeMismatch, + PropertyWriteFailed +}; + +static QDBusMessage propertyWriteReply(const QDBusMessage &msg, const QString &interface_name, + const QByteArray &property_name, int status) +{ + switch (status) { + case PropertyNotFound: + return propertyNotFoundError(msg, interface_name, property_name); + case PropertyTypeMismatch: + return msg.createErrorReply(QDBusError::InvalidArgs, + QString::fromLatin1("Invalid arguments for writing to property %1%2%3") + .arg(interface_name, + QString::fromLatin1(interface_name.isEmpty() ? "" : "."), + QString::fromLatin1(property_name))); + case PropertyWriteFailed: + return msg.createErrorReply(QDBusError::InternalError, + QString::fromLatin1("Internal error")); + + case PropertyWriteSuccess: + return msg.createReply(); + } + Q_ASSERT_X(false, "", "Should not be reached"); + return QDBusMessage(); +} + +static int writeProperty(QObject *obj, const QByteArray &property_name, QVariant value, + int propFlags = QDBusConnection::ExportAllProperties) +{ + const QMetaObject *mo = obj->metaObject(); + int pidx = mo->indexOfProperty(property_name); + if (pidx == -1) { + // this object has no property by that name + return PropertyNotFound; + } + + QMetaProperty mp = mo->property(pidx); + + // check if this property is exported + bool isScriptable = mp.isScriptable(); + if (!(propFlags & QDBusConnection::ExportScriptableProperties) && isScriptable) + return PropertyNotFound; + if (!(propFlags & QDBusConnection::ExportNonScriptableProperties) && !isScriptable) + return PropertyNotFound; + + // we found our property + // do we have the right type? + int id = mp.type(); + if (id == QVariant::UserType) { + // dynamic type + id = qDBusNameToTypeId(mp.typeName()); + if (id == -1) { + // type not registered? + qWarning("QDBusConnection: Unable to handle unregistered datatype '%s' for property '%s::%s'", + mp.typeName(), mo->className(), property_name.constData()); + return PropertyWriteFailed; + } + } + + if (id != 0xff && value.userType() == QDBusMetaTypeId::argument) { + // we have to demarshall before writing + void *null = 0; + QVariant other(id, null); + if (!QDBusMetaType::demarshall(qVariantValue(value), id, other.data())) { + qWarning("QDBusConnection: type `%s' (%d) is not registered with QtDBus. " + "Use qDBusRegisterMetaType to register it", + mp.typeName(), id); + return PropertyWriteFailed; + } + + value = other; + } + + // the property type here should match + return mp.write(obj, value) ? PropertyWriteSuccess : PropertyWriteFailed; +} + QDBusMessage qDBusPropertySet(const QDBusConnectionPrivate::ObjectTreeNode &node, const QDBusMessage &msg) { @@ -263,38 +367,39 @@ QDBusMessage qDBusPropertySet(const QDBusConnectionPrivate::ObjectTreeNode &node if (interface_name.isEmpty()) { for (QDBusAdaptorConnector::AdaptorMap::ConstIterator it = connector->adaptors.constBegin(), end = connector->adaptors.constEnd(); it != end; ++it) { - const QMetaObject *mo = it->adaptor->metaObject(); - int pidx = mo->indexOfProperty(property_name); - if (pidx != -1) { - mo->property(pidx).write(it->adaptor, value); - return msg.createReply(); - } + int status = writeProperty(it->adaptor, property_name, value); + if (status == PropertyNotFound) + continue; + return propertyWriteReply(msg, interface_name, property_name, status); } } else { QDBusAdaptorConnector::AdaptorMap::ConstIterator it; it = qLowerBound(connector->adaptors.constBegin(), connector->adaptors.constEnd(), interface_name); - if (it != connector->adaptors.end() && interface_name == QLatin1String(it->interface)) - if (it->adaptor->setProperty(property_name, value)) - return msg.createReply(); + if (it != connector->adaptors.end() && interface_name == QLatin1String(it->interface)) { + return propertyWriteReply(msg, interface_name, property_name, + writeProperty(it->adaptor, property_name, value)); + } } } if (node.flags & (QDBusConnection::ExportScriptableProperties | QDBusConnection::ExportNonScriptableProperties)) { // try the object itself - int pidx = node.obj->metaObject()->indexOfProperty(property_name); - if (pidx != -1) { - QMetaProperty mp = node.obj->metaObject()->property(pidx); - if ((mp.isScriptable() && (node.flags & QDBusConnection::ExportScriptableProperties)) || - (!mp.isScriptable() && (node.flags & QDBusConnection::ExportNonScriptableProperties))) - if (mp.write(node.obj, value)) - return msg.createReply(); + bool interfaceFound = true; + if (!interface_name.isEmpty()) + interfaceFound = qDBusInterfaceInObject(node.obj, interface_name); + + if (interfaceFound) { + return propertyWriteReply(msg, interface_name, property_name, + writeProperty(node.obj, property_name, value, node.flags)); } } - // the property was not found or not written to - return qDBusPropertyError(msg, interface_name); + // the property was not found + if (!interface_name.isEmpty()) + return interfaceNotFoundError(msg, interface_name); + return propertyWriteReply(msg, interface_name, property_name, PropertyNotFound); } // unite two QVariantMaps, but don't generate duplicate keys @@ -385,7 +490,7 @@ QDBusMessage qDBusPropertyGetAll(const QDBusConnectionPrivate::ObjectTreeNode &n if (!interfaceFound && !interface_name.isEmpty()) { // the interface was not found - return qDBusPropertyError(msg, interface_name); + return interfaceNotFoundError(msg, interface_name); } return msg.createReply(qVariantFromValue(result)); -- cgit v0.12 From a80d8f015f68cb2b6d5f4cc8b2893543122c5d2b Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 29 Jun 2009 16:16:57 +0200 Subject: Autotest: make sure we create the QDBusInterface after the object exists. The current code allows making calls to QDBusInterface objects that failed to introspect. It's technically a valid condition. You won't be able to connect to signals, get or set properties, but making calls was possible. I don't know if I want to keep this change in behaviour. --- .../tst_qdbusabstractadaptor.cpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/tests/auto/qdbusabstractadaptor/tst_qdbusabstractadaptor.cpp b/tests/auto/qdbusabstractadaptor/tst_qdbusabstractadaptor.cpp index c70c619..5d08c63 100644 --- a/tests/auto/qdbusabstractadaptor/tst_qdbusabstractadaptor.cpp +++ b/tests/auto/qdbusabstractadaptor/tst_qdbusabstractadaptor.cpp @@ -609,19 +609,22 @@ void tst_QDBusAbstractAdaptor::methodCalls() QVERIFY(con.isConnected()); //QDBusInterface emptycon.baseService(), "/", QString()); - QDBusInterface if1(con.baseService(), "/", "local.Interface1", con); - QDBusInterface if2(con.baseService(), "/", "local.Interface2", con); - QDBusInterface if3(con.baseService(), "/", "local.Interface3", con); - QDBusInterface if4(con.baseService(), "/", "local.Interface4", con); - // must fail: no object - //QCOMPARE(empty->call("method").type(), QDBusMessage::ErrorMessage); - QCOMPARE(if1.call(QDBus::BlockWithGui, "method").type(), QDBusMessage::ErrorMessage); + { + // must fail: no object + QDBusInterface if1(con.baseService(), "/", "local.Interface1", con); + QCOMPARE(if1.call(QDBus::BlockWithGui, "method").type(), QDBusMessage::ErrorMessage); + } QFETCH(int, nInterfaces); MyObject obj(nInterfaces); con.registerObject("/", &obj); + QDBusInterface if1(con.baseService(), "/", "local.Interface1", con); + QDBusInterface if2(con.baseService(), "/", "local.Interface2", con); + QDBusInterface if3(con.baseService(), "/", "local.Interface3", con); + QDBusInterface if4(con.baseService(), "/", "local.Interface4", con); + // must fail: no such method QCOMPARE(if1.call(QDBus::BlockWithGui, "method").type(), QDBusMessage::ErrorMessage); if (!nInterfaces--) @@ -670,11 +673,11 @@ void tst_QDBusAbstractAdaptor::methodCallScriptable() QDBusConnection con = QDBusConnection::sessionBus(); QVERIFY(con.isConnected()); - QDBusInterface if2(con.baseService(), "/", "local.Interface2", con); - MyObject obj(2); con.registerObject("/", &obj); + QDBusInterface if2(con.baseService(), "/", "local.Interface2", con); + QCOMPARE(if2.call(QDBus::BlockWithGui,"scriptableMethod").type(), QDBusMessage::ReplyMessage); QCOMPARE(slotSpy, "void Interface2::scriptableMethod()"); } -- cgit v0.12 From d675a1f752f6acb57c66082b9b25e1b8aa337f8a Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 30 Jun 2009 11:15:22 +0200 Subject: Autotest: add tests for method call errors --- tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp | 105 ++++++++++++++++++++++++- 1 file changed, 103 insertions(+), 2 deletions(-) diff --git a/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp b/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp index 3ba789a..e304712 100644 --- a/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp +++ b/tests/auto/qdbusmarshall/tst_qdbusmarshall.cpp @@ -84,12 +84,17 @@ private slots: void sendArgument_data(); void sendArgument(); - void sendErrors(); + void sendSignalErrors(); + void sendCallErrors_data(); + void sendCallErrors(); private: QProcess proc; }; +struct UnregisteredType { }; +Q_DECLARE_METATYPE(UnregisteredType) + class WaitForQPong: public QObject { Q_OBJECT @@ -784,7 +789,7 @@ void tst_QDBusMarshall::sendArgument() QCOMPARE(extracted, value); } -void tst_QDBusMarshall::sendErrors() +void tst_QDBusMarshall::sendSignalErrors() { QDBusConnection con = QDBusConnection::sessionBus(); @@ -819,5 +824,101 @@ void tst_QDBusMarshall::sendErrors() QVERIFY(!con.send(msg)); } +void tst_QDBusMarshall::sendCallErrors_data() +{ + QTest::addColumn("service"); + QTest::addColumn("path"); + QTest::addColumn("interface"); + QTest::addColumn("method"); + QTest::addColumn("arguments"); + QTest::addColumn("errorName"); + QTest::addColumn("errorMsg"); + QTest::addColumn("ignoreMsg"); + + // this error comes from the bus server + QTest::newRow("empty-service") << "" << objectPath << interfaceName << "ping" << QVariantList() + << "org.freedesktop.DBus.Error.UnknownMethod" + << "Method \"ping\" with signature \"\" on interface \"com.trolltech.autotests.qpong\" doesn't exist\n" << (const char*)0; + + QTest::newRow("invalid-service") << "this isn't valid" << objectPath << interfaceName << "ping" << QVariantList() + << "com.trolltech.QtDBus.Error.InvalidService" + << "Invalid service name: this isn't valid" << ""; + + QTest::newRow("empty-path") << serviceName << "" << interfaceName << "ping" << QVariantList() + << "com.trolltech.QtDBus.Error.InvalidObjectPath" + << "Object path cannot be empty" << ""; + QTest::newRow("invalid-path") << serviceName << "//" << interfaceName << "ping" << QVariantList() + << "com.trolltech.QtDBus.Error.InvalidObjectPath" + << "Invalid object path: //" << ""; + + // empty interfaces are valid + QTest::newRow("invalid-interface") << serviceName << objectPath << "this isn't valid" << "ping" << QVariantList() + << "com.trolltech.QtDBus.Error.InvalidInterface" + << "Invalid interface class: this isn't valid" << ""; + + QTest::newRow("empty-method") << serviceName << objectPath << interfaceName << "" << QVariantList() + << "com.trolltech.QtDBus.Error.InvalidMember" + << "method name cannot be empty" << ""; + QTest::newRow("invalid-method") << serviceName << objectPath << interfaceName << "this isn't valid" << QVariantList() + << "com.trolltech.QtDBus.Error.InvalidMember" + << "Invalid method name: this isn't valid" << ""; + + QTest::newRow("invalid-variant1") << serviceName << objectPath << interfaceName << "ping" + << (QVariantList() << QVariant()) + << "org.freedesktop.DBus.Error.Failed" + << "Marshalling failed: Variant containing QVariant::Invalid passed in arguments" + << "QDBusMarshaller: cannot add an invalid QVariant"; + QTest::newRow("invalid-variant1") << serviceName << objectPath << interfaceName << "ping" + << (QVariantList() << qVariantFromValue(QDBusVariant())) + << "org.freedesktop.DBus.Error.Failed" + << "Marshalling failed: Variant containing QVariant::Invalid passed in arguments" + << "QDBusMarshaller: cannot add a null QDBusVariant"; + + QTest::newRow("builtin-unregistered") << serviceName << objectPath << interfaceName << "ping" + << (QVariantList() << QLocale::c()) + << "org.freedesktop.DBus.Error.Failed" + << "Marshalling failed: Unregistered type QLocale passed in arguments" + << "QDBusMarshaller: type `QLocale' (18) is not registered with D-BUS. Use qDBusRegisterMetaType to register it"; + + // this type is known to the meta type system, but not registered with D-Bus + qRegisterMetaType(); + QTest::newRow("extra-unregistered") << serviceName << objectPath << interfaceName << "ping" + << (QVariantList() << qVariantFromValue(UnregisteredType())) + << "org.freedesktop.DBus.Error.Failed" + << "Marshalling failed: Unregistered type UnregisteredType passed in arguments" + << QString("QDBusMarshaller: type `UnregisteredType' (%1) is not registered with D-BUS. Use qDBusRegisterMetaType to register it") + .arg(qMetaTypeId()); +} + +void tst_QDBusMarshall::sendCallErrors() +{ + QDBusConnection con = QDBusConnection::sessionBus(); + QVERIFY(con.isConnected()); + + QFETCH(QString, service); + QFETCH(QString, path); + QFETCH(QString, interface); + QFETCH(QString, method); + QFETCH(QVariantList, arguments); + QFETCH(QString, errorMsg); + + QFETCH(QString, ignoreMsg); + if (!ignoreMsg.isEmpty()) + QTest::ignoreMessage(QtWarningMsg, ignoreMsg.toLatin1()); + if (!ignoreMsg.isNull()) + QTest::ignoreMessage(QtWarningMsg, + QString("QDBusConnection: error: could not send message to service \"%1\" path \"%2\" interface \"%3\" member \"%4\": %5") + .arg(service, path, interface, method, errorMsg) + .toLatin1()); + + QDBusMessage msg = QDBusMessage::createMethodCall(service, path, interface, method); + msg.setArguments(arguments); + + QDBusMessage reply = con.call(msg, QDBus::Block); + QCOMPARE(reply.type(), QDBusMessage::ErrorMessage); + QTEST(reply.errorName(), "errorName"); + QCOMPARE(reply.errorMessage(), errorMsg); +} + QTEST_MAIN(tst_QDBusMarshall) #include "tst_qdbusmarshall.moc" -- cgit v0.12 From 202167643206bbfb50cce605fdfbd4cfef843bad Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 30 Jun 2009 16:21:44 +0200 Subject: Autotest: Add testing of QDBusAbstractInterface --- tests/auto/auto.pro | 1 + .../com.trolltech.QtDBus.Pinger.xml | 29 ++ tests/auto/qdbusabstractinterface/interface.cpp | 48 ++ tests/auto/qdbusabstractinterface/interface.h | 109 +++++ tests/auto/qdbusabstractinterface/pinger.cpp | 67 +++ tests/auto/qdbusabstractinterface/pinger.h | 139 ++++++ .../qdbusabstractinterface.pro | 15 + .../tst_qdbusabstractinterface.cpp | 529 +++++++++++++++++++++ 8 files changed, 937 insertions(+) create mode 100644 tests/auto/qdbusabstractinterface/com.trolltech.QtDBus.Pinger.xml create mode 100644 tests/auto/qdbusabstractinterface/interface.cpp create mode 100644 tests/auto/qdbusabstractinterface/interface.h create mode 100644 tests/auto/qdbusabstractinterface/pinger.cpp create mode 100644 tests/auto/qdbusabstractinterface/pinger.h create mode 100644 tests/auto/qdbusabstractinterface/qdbusabstractinterface.pro create mode 100644 tests/auto/qdbusabstractinterface/tst_qdbusabstractinterface.cpp diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index fd887fd..8bc2ed9 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -419,6 +419,7 @@ xmlpatternsxslts.depends = xmlpatternsxqts unix:!embedded:contains(QT_CONFIG, dbus):SUBDIRS += \ qdbusabstractadaptor \ + qdbusabstractinterface \ qdbusconnection \ qdbusinterface \ qdbuslocalcalls \ diff --git a/tests/auto/qdbusabstractinterface/com.trolltech.QtDBus.Pinger.xml b/tests/auto/qdbusabstractinterface/com.trolltech.QtDBus.Pinger.xml new file mode 100644 index 0000000..8909675 --- /dev/null +++ b/tests/auto/qdbusabstractinterface/com.trolltech.QtDBus.Pinger.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/auto/qdbusabstractinterface/interface.cpp b/tests/auto/qdbusabstractinterface/interface.cpp new file mode 100644 index 0000000..1c391ce --- /dev/null +++ b/tests/auto/qdbusabstractinterface/interface.cpp @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "interface.h" + +Interface::Interface() +{ +} + +#include "moc_interface.cpp" diff --git a/tests/auto/qdbusabstractinterface/interface.h b/tests/auto/qdbusabstractinterface/interface.h new file mode 100644 index 0000000..86e0dc4 --- /dev/null +++ b/tests/auto/qdbusabstractinterface/interface.h @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef INTERFACE_H +#define INTERFACE_H + +#include +#include + +struct RegisteredType +{ + inline RegisteredType(const QString &str = QString()) : s(str) {} + inline bool operator==(const RegisteredType &other) const { return s == other.s; } + QString s; +}; +Q_DECLARE_METATYPE(RegisteredType) + +inline QDBusArgument &operator<<(QDBusArgument &s, const RegisteredType &data) +{ + s.beginStructure(); + s << data.s; + s.endStructure(); + return s; +} + +inline const QDBusArgument &operator>>(const QDBusArgument &s, RegisteredType &data) +{ + s.beginStructure(); + s >> data.s; + s.endStructure(); + return s; +} + +struct UnregisteredType +{ + QString s; +}; +Q_DECLARE_METATYPE(UnregisteredType) + +class Interface: public QObject +{ + Q_OBJECT + Q_CLASSINFO("D-Bus Interface", "com.trolltech.QtDBus.Pinger") + Q_PROPERTY(QString stringProp READ stringProp WRITE setStringProp SCRIPTABLE true) + Q_PROPERTY(RegisteredType complexProp READ complexProp WRITE setComplexProp SCRIPTABLE true) + + friend class tst_QDBusAbstractInterface; + QString m_stringProp; + RegisteredType m_complexProp; + +public: + Interface(); + + QString stringProp() const { return m_stringProp; } + void setStringProp(const QString &s) { m_stringProp = s; } + RegisteredType complexProp() const { return m_complexProp; } + void setComplexProp(const RegisteredType &r) { m_complexProp = r; } + +public slots: + Q_SCRIPTABLE void voidMethod() {} + Q_SCRIPTABLE QString stringMethod() { return "Hello, world"; } + Q_SCRIPTABLE RegisteredType complexMethod() { return RegisteredType("Hello, world"); } + Q_SCRIPTABLE QString multiOutMethod(int &value) { value = 42; return "Hello, world"; } + +signals: + Q_SCRIPTABLE void voidSignal(); + Q_SCRIPTABLE void stringSignal(const QString &); + Q_SCRIPTABLE void complexSignal(RegisteredType); +}; + +#endif // INTERFACE_H diff --git a/tests/auto/qdbusabstractinterface/pinger.cpp b/tests/auto/qdbusabstractinterface/pinger.cpp new file mode 100644 index 0000000..4fcb89a --- /dev/null +++ b/tests/auto/qdbusabstractinterface/pinger.cpp @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDBus module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/* + * This file was generated by qdbusxml2cpp version 0.7 + * Command line was: qdbusxml2cpp -i interface.h -p pinger com.trolltech.QtDBus.Pinger.xml + * + * qdbusxml2cpp is Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). + * + * This is an auto-generated file. + * This file may have been hand-edited. Look for HAND-EDIT comments + * before re-generating it. + */ + +#include "pinger.h" + +/* + * Implementation of interface class ComTrolltechQtDBusPingerInterface + */ + +ComTrolltechQtDBusPingerInterface::ComTrolltechQtDBusPingerInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent) + : QDBusAbstractInterface(service, path, staticInterfaceName(), connection, parent) +{ +} + +ComTrolltechQtDBusPingerInterface::~ComTrolltechQtDBusPingerInterface() +{ +} + diff --git a/tests/auto/qdbusabstractinterface/pinger.h b/tests/auto/qdbusabstractinterface/pinger.h new file mode 100644 index 0000000..3ff218c --- /dev/null +++ b/tests/auto/qdbusabstractinterface/pinger.h @@ -0,0 +1,139 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDBus module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/* + * This file was generated by qdbusxml2cpp version 0.7 + * Command line was: qdbusxml2cpp -i interface.h -p pinger com.trolltech.QtDBus.Pinger.xml + * + * qdbusxml2cpp is Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). + * + * This is an auto-generated file. + * Do not edit! All changes made to it will be lost. + */ + +#ifndef PINGER_H_1246371899 +#define PINGER_H_1246371899 + +#include +#include +#include +#include +#include +#include +#include +#include +#include "interface.h" + +/* + * Proxy class for interface com.trolltech.QtDBus.Pinger + */ +class ComTrolltechQtDBusPingerInterface: public QDBusAbstractInterface +{ + Q_OBJECT +public: + static inline const char *staticInterfaceName() + { return "com.trolltech.QtDBus.Pinger"; } + +public: + ComTrolltechQtDBusPingerInterface(const QString &service, const QString &path, const QDBusConnection &connection, QObject *parent = 0); + + ~ComTrolltechQtDBusPingerInterface(); + + Q_PROPERTY(RegisteredType complexProp READ complexProp WRITE setComplexProp) + inline RegisteredType complexProp() const + { return qvariant_cast< RegisteredType >(internalPropGet("complexProp")); } + inline void setComplexProp(RegisteredType value) + { internalPropSet("complexProp", qVariantFromValue(value)); } + + Q_PROPERTY(QString stringProp READ stringProp WRITE setStringProp) + inline QString stringProp() const + { return qvariant_cast< QString >(internalPropGet("stringProp")); } + inline void setStringProp(const QString &value) + { internalPropSet("stringProp", qVariantFromValue(value)); } + +public Q_SLOTS: // METHODS + inline QDBusPendingReply complexMethod() + { + QList argumentList; + return asyncCallWithArgumentList(QLatin1String("complexMethod"), argumentList); + } + + inline QDBusPendingReply multiOutMethod() + { + QList argumentList; + return asyncCallWithArgumentList(QLatin1String("multiOutMethod"), argumentList); + } + inline QDBusReply multiOutMethod(int &out1) + { + QList argumentList; + QDBusMessage reply = callWithArgumentList(QDBus::Block, QLatin1String("multiOutMethod"), argumentList); + if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == 2) { + out1 = qdbus_cast(reply.arguments().at(1)); + } + return reply; + } + + inline QDBusPendingReply stringMethod() + { + QList argumentList; + return asyncCallWithArgumentList(QLatin1String("stringMethod"), argumentList); + } + + inline QDBusPendingReply<> voidMethod() + { + QList argumentList; + return asyncCallWithArgumentList(QLatin1String("voidMethod"), argumentList); + } + +Q_SIGNALS: // SIGNALS + void complexSignal(RegisteredType in0); + void stringSignal(const QString &in0); + void voidSignal(); +}; + +namespace com { + namespace trolltech { + namespace QtDBus { + typedef ::ComTrolltechQtDBusPingerInterface Pinger; + } + } +} +#endif diff --git a/tests/auto/qdbusabstractinterface/qdbusabstractinterface.pro b/tests/auto/qdbusabstractinterface/qdbusabstractinterface.pro new file mode 100644 index 0000000..a4853b8 --- /dev/null +++ b/tests/auto/qdbusabstractinterface/qdbusabstractinterface.pro @@ -0,0 +1,15 @@ +load(qttest_p4) +QT = core +contains(QT_CONFIG,dbus): { + SOURCES += tst_qdbusabstractinterface.cpp interface.cpp + HEADERS += interface.h + QT += dbus + + # These are generated sources + # To regenerate, see the command-line at the top of the files + SOURCES += pinger.cpp + HEADERS += pinger.h +} +else:SOURCES += ../qdbusmarshall/dummy.cpp + +OTHER_FILES += com.trolltech.QtDBus.Pinger.xml diff --git a/tests/auto/qdbusabstractinterface/tst_qdbusabstractinterface.cpp b/tests/auto/qdbusabstractinterface/tst_qdbusabstractinterface.cpp new file mode 100644 index 0000000..4aee089 --- /dev/null +++ b/tests/auto/qdbusabstractinterface/tst_qdbusabstractinterface.cpp @@ -0,0 +1,529 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include +#include +#include + +#include + +#include + +#include "interface.h" +#include "pinger.h" + +typedef QSharedPointer Pinger; + +class tst_QDBusAbstractInterface: public QObject +{ + Q_OBJECT + Interface targetObj; + + Pinger getPinger(QString service = "", const QString &path = "/") + { + QDBusConnection con = QDBusConnection::sessionBus(); + if (!con.isConnected()) + return Pinger(); + if (service.isEmpty() && !service.isNull()) + service = con.baseService(); + return Pinger(new com::trolltech::QtDBus::Pinger(service, path, con)); + } + +public: + tst_QDBusAbstractInterface(); + +private slots: + void initTestCase(); + + void makeVoidCall(); + void makeStringCall(); + void makeComplexCall(); + void makeMultiOutCall(); + + void makeAsyncVoidCall(); + void makeAsyncStringCall(); + void makeAsyncComplexCall(); + void makeAsyncMultiOutCall(); + + void stringPropRead(); + void stringPropWrite(); + void complexPropRead(); + void complexPropWrite(); + + void stringPropDirectRead(); + void stringPropDirectWrite(); + void complexPropDirectRead(); + void complexPropDirectWrite(); + + void getVoidSignal_data(); + void getVoidSignal(); + void getStringSignal_data(); + void getStringSignal(); + void getComplexSignal_data(); + void getComplexSignal(); + + void createErrors_data(); + void createErrors(); + + void callErrors_data(); + void callErrors(); + void asyncCallErrors_data(); + void asyncCallErrors(); + + void propertyReadErrors_data(); + void propertyReadErrors(); + void propertyWriteErrors_data(); + void propertyWriteErrors(); + void directPropertyReadErrors_data(); + void directPropertyReadErrors(); + void directPropertyWriteErrors_data(); + void directPropertyWriteErrors(); +}; + +tst_QDBusAbstractInterface::tst_QDBusAbstractInterface() +{ + // register the meta types + qDBusRegisterMetaType(); + qRegisterMetaType(); +} + +void tst_QDBusAbstractInterface::initTestCase() +{ + // register the object + QDBusConnection con = QDBusConnection::sessionBus(); + QVERIFY(con.isConnected()); + con.registerObject("/", &targetObj, QDBusConnection::ExportScriptableContents); +} + +void tst_QDBusAbstractInterface::makeVoidCall() +{ + Pinger p = getPinger(); + QVERIFY2(p, "Not connected to D-Bus"); + + QDBusReply r = p->voidMethod(); + QVERIFY(r.isValid()); +} + +void tst_QDBusAbstractInterface::makeStringCall() +{ + Pinger p = getPinger(); + QVERIFY2(p, "Not connected to D-Bus"); + + QDBusReply r = p->stringMethod(); + QVERIFY(r.isValid()); + QCOMPARE(r.value(), targetObj.stringMethod()); +} + +void tst_QDBusAbstractInterface::makeComplexCall() +{ + Pinger p = getPinger(); + QVERIFY2(p, "Not connected to D-Bus"); + + QDBusReply r = p->complexMethod(); + QVERIFY(r.isValid()); + QCOMPARE(r.value(), targetObj.complexMethod()); +} + +void tst_QDBusAbstractInterface::makeMultiOutCall() +{ + Pinger p = getPinger(); + QVERIFY2(p, "Not connected to D-Bus"); + + int value; + QDBusReply r = p->multiOutMethod(value); + QVERIFY(r.isValid()); + + int expectedValue; + QCOMPARE(r.value(), targetObj.multiOutMethod(expectedValue)); + QCOMPARE(value, expectedValue); +} + +void tst_QDBusAbstractInterface::makeAsyncVoidCall() +{ + Pinger p = getPinger(); + QVERIFY2(p, "Not connected to D-Bus"); + + QDBusPendingReply r = p->voidMethod(); + r.waitForFinished(); + QVERIFY(r.isValid()); +} + +void tst_QDBusAbstractInterface::makeAsyncStringCall() +{ + Pinger p = getPinger(); + QVERIFY2(p, "Not connected to D-Bus"); + + QDBusPendingReply r = p->stringMethod(); + r.waitForFinished(); + QVERIFY(r.isValid()); + QCOMPARE(r.value(), targetObj.stringMethod()); +} + +void tst_QDBusAbstractInterface::makeAsyncComplexCall() +{ + Pinger p = getPinger(); + QVERIFY2(p, "Not connected to D-Bus"); + + QDBusPendingReply r = p->complexMethod(); + r.waitForFinished(); + QVERIFY(r.isValid()); + QCOMPARE(r.value(), targetObj.complexMethod()); +} + +void tst_QDBusAbstractInterface::makeAsyncMultiOutCall() +{ + Pinger p = getPinger(); + QVERIFY2(p, "Not connected to D-Bus"); + + QDBusPendingReply r = p->multiOutMethod(); + r.waitForFinished(); + QVERIFY(r.isValid()); + + int expectedValue; + QCOMPARE(r.value(), targetObj.multiOutMethod(expectedValue)); + QCOMPARE(r.argumentAt<1>(), expectedValue); +} + +void tst_QDBusAbstractInterface::stringPropRead() +{ + Pinger p = getPinger(); + QVERIFY2(p, "Not connected to D-Bus"); + + QString expectedValue = targetObj.m_stringProp = "This is a test"; + QVariant v = p->property("stringProp"); + QVERIFY(v.isValid()); + QCOMPARE(v.toString(), expectedValue); +} + +void tst_QDBusAbstractInterface::stringPropWrite() +{ + Pinger p = getPinger(); + QVERIFY2(p, "Not connected to D-Bus"); + + QString expectedValue = "This is a value"; + QVERIFY(p->setProperty("stringProp", expectedValue)); + QCOMPARE(targetObj.m_stringProp, expectedValue); +} + +void tst_QDBusAbstractInterface::complexPropRead() +{ + Pinger p = getPinger(); + QVERIFY2(p, "Not connected to D-Bus"); + + RegisteredType expectedValue = targetObj.m_complexProp = RegisteredType("This is a test"); + QVariant v = p->property("complexProp"); + QVERIFY(v.userType() == qMetaTypeId()); + QCOMPARE(v.value(), targetObj.m_complexProp); +} + +void tst_QDBusAbstractInterface::complexPropWrite() +{ + Pinger p = getPinger(); + QVERIFY2(p, "Not connected to D-Bus"); + + RegisteredType expectedValue = RegisteredType("This is a value"); + QVERIFY(p->setProperty("complexProp", qVariantFromValue(expectedValue))); + QCOMPARE(targetObj.m_complexProp, expectedValue); +} + +void tst_QDBusAbstractInterface::stringPropDirectRead() +{ + Pinger p = getPinger(); + QVERIFY2(p, "Not connected to D-Bus"); + + QString expectedValue = targetObj.m_stringProp = "This is a test"; + QCOMPARE(p->stringProp(), expectedValue); +} + +void tst_QDBusAbstractInterface::stringPropDirectWrite() +{ + Pinger p = getPinger(); + QVERIFY2(p, "Not connected to D-Bus"); + + QString expectedValue = "This is a value"; + p->setStringProp(expectedValue); + QCOMPARE(targetObj.m_stringProp, expectedValue); +} + +void tst_QDBusAbstractInterface::complexPropDirectRead() +{ + Pinger p = getPinger(); + QVERIFY2(p, "Not connected to D-Bus"); + + RegisteredType expectedValue = targetObj.m_complexProp = RegisteredType("This is a test"); + QCOMPARE(p->complexProp(), targetObj.m_complexProp); +} + +void tst_QDBusAbstractInterface::complexPropDirectWrite() +{ + Pinger p = getPinger(); + QVERIFY2(p, "Not connected to D-Bus"); + + RegisteredType expectedValue = RegisteredType("This is a value"); + p->setComplexProp(expectedValue); + QCOMPARE(targetObj.m_complexProp, expectedValue); +} + +void tst_QDBusAbstractInterface::getVoidSignal_data() +{ + QTest::addColumn("service"); + QTest::addColumn("path"); + + QTest::newRow("specific") << QDBusConnection::sessionBus().baseService() << "/"; + QTest::newRow("service-wildcard") << QString() << "/"; + QTest::newRow("path-wildcard") << QDBusConnection::sessionBus().baseService() << QString(); + QTest::newRow("full-wildcard") << QString() << QString(); +} + +void tst_QDBusAbstractInterface::getVoidSignal() +{ + QFETCH(QString, service); + QFETCH(QString, path); + Pinger p = getPinger(service, path); + QVERIFY2(p, "Not connected to D-Bus"); + + // we need to connect the signal somewhere in order for D-Bus to enable the rules + QTestEventLoop::instance().connect(p.data(), SIGNAL(voidSignal()), SLOT(exitLoop())); + QSignalSpy s(p.data(), SIGNAL(voidSignal())); + + emit targetObj.voidSignal(); + QTestEventLoop::instance().enterLoop(2); + QVERIFY(!QTestEventLoop::instance().timeout()); + + QVERIFY(s.size() == 1); + QVERIFY(s.at(0).size() == 0); +} + +void tst_QDBusAbstractInterface::getStringSignal_data() +{ + getVoidSignal_data(); +} + +void tst_QDBusAbstractInterface::getStringSignal() +{ + QFETCH(QString, service); + QFETCH(QString, path); + Pinger p = getPinger(service, path); + QVERIFY2(p, "Not connected to D-Bus"); + + // we need to connect the signal somewhere in order for D-Bus to enable the rules + QTestEventLoop::instance().connect(p.data(), SIGNAL(stringSignal(QString)), SLOT(exitLoop())); + QSignalSpy s(p.data(), SIGNAL(stringSignal(QString))); + + QString expectedValue = "Good morning"; + emit targetObj.stringSignal(expectedValue); + QTestEventLoop::instance().enterLoop(2); + QVERIFY(!QTestEventLoop::instance().timeout()); + + QVERIFY(s.size() == 1); + QVERIFY(s[0].size() == 1); + QCOMPARE(s[0][0].userType(), int(QVariant::String)); + QCOMPARE(s[0][0].toString(), expectedValue); +} + +void tst_QDBusAbstractInterface::getComplexSignal_data() +{ + getVoidSignal_data(); +} + +void tst_QDBusAbstractInterface::getComplexSignal() +{ + QFETCH(QString, service); + QFETCH(QString, path); + Pinger p = getPinger(service, path); + QVERIFY2(p, "Not connected to D-Bus"); + + // we need to connect the signal somewhere in order for D-Bus to enable the rules + QTestEventLoop::instance().connect(p.data(), SIGNAL(complexSignal(RegisteredType)), SLOT(exitLoop())); + QSignalSpy s(p.data(), SIGNAL(complexSignal(RegisteredType))); + + RegisteredType expectedValue("Good evening"); + emit targetObj.complexSignal(expectedValue); + QTestEventLoop::instance().enterLoop(2); + QVERIFY(!QTestEventLoop::instance().timeout()); + + QVERIFY(s.size() == 1); + QVERIFY(s[0].size() == 1); + QCOMPARE(s[0][0].userType(), qMetaTypeId()); + QCOMPARE(s[0][0].value(), expectedValue); +} + +void tst_QDBusAbstractInterface::createErrors_data() +{ + QTest::addColumn("service"); + QTest::addColumn("path"); + QTest::addColumn("errorName"); + + QTest::newRow("invalid-service") << "this isn't valid" << "/" << "com.trolltech.QtDBus.Error.InvalidService"; + QTest::newRow("invalid-path") << QDBusConnection::sessionBus().baseService() << "this isn't valid" + << "com.trolltech.QtDBus.Error.InvalidObjectPath"; +} + +void tst_QDBusAbstractInterface::createErrors() +{ + QFETCH(QString, service); + QFETCH(QString, path); + Pinger p = getPinger(service, path); + QVERIFY2(p, "Not connected to D-Bus"); + + QVERIFY(!p->isValid()); + QTEST(p->lastError().name(), "errorName"); +} + +void tst_QDBusAbstractInterface::callErrors_data() +{ + createErrors_data(); + QTest::newRow("service-wildcard") << QString() << "/" << "com.trolltech.QtDBus.Error.InvalidService"; + QTest::newRow("path-wildcard") << QDBusConnection::sessionBus().baseService() << QString() + << "com.trolltech.QtDBus.Error.InvalidObjectPath"; + QTest::newRow("full-wildcard") << QString() << QString() << "com.trolltech.QtDBus.Error.InvalidService"; +} + +void tst_QDBusAbstractInterface::callErrors() +{ + QFETCH(QString, service); + QFETCH(QString, path); + Pinger p = getPinger(service, path); + QVERIFY2(p, "Not connected to D-Bus"); + + // we shouldn't be able to make this call: + QDBusReply r = p->stringMethod(); + QVERIFY(!r.isValid()); + QTEST(r.error().name(), "errorName"); + QCOMPARE(p->lastError().name(), r.error().name()); +} + +void tst_QDBusAbstractInterface::asyncCallErrors_data() +{ + callErrors_data(); +} + +void tst_QDBusAbstractInterface::asyncCallErrors() +{ + QFETCH(QString, service); + QFETCH(QString, path); + Pinger p = getPinger(service, path); + QVERIFY2(p, "Not connected to D-Bus"); + + // we shouldn't be able to make this call: + QDBusPendingReply r = p->stringMethod(); + QVERIFY(r.isError()); + QTEST(r.error().name(), "errorName"); + QCOMPARE(p->lastError().name(), r.error().name()); +} + +void tst_QDBusAbstractInterface::propertyReadErrors_data() +{ + callErrors_data(); +} + +void tst_QDBusAbstractInterface::propertyReadErrors() +{ + QFETCH(QString, service); + QFETCH(QString, path); + Pinger p = getPinger(service, path); + QVERIFY2(p, "Not connected to D-Bus"); + + // we shouldn't be able to get this value: + QVariant v = p->property("stringProp"); + QVERIFY(v.isNull()); + QVERIFY(!v.isValid()); + QTEST(p->lastError().name(), "errorName"); +} + +void tst_QDBusAbstractInterface::propertyWriteErrors_data() +{ + callErrors_data(); +} + +void tst_QDBusAbstractInterface::propertyWriteErrors() +{ + QFETCH(QString, service); + QFETCH(QString, path); + Pinger p = getPinger(service, path); + QVERIFY2(p, "Not connected to D-Bus"); + + // we shouldn't be able to get this value: + if (p->isValid()) + QCOMPARE(int(p->lastError().type()), int(QDBusError::NoError)); + QVERIFY(!p->setProperty("stringProp", "")); + QTEST(p->lastError().name(), "errorName"); +} + +void tst_QDBusAbstractInterface::directPropertyReadErrors_data() +{ + callErrors_data(); +} + +void tst_QDBusAbstractInterface::directPropertyReadErrors() +{ + QFETCH(QString, service); + QFETCH(QString, path); + Pinger p = getPinger(service, path); + QVERIFY2(p, "Not connected to D-Bus"); + + // we shouldn't be able to get this value: + QString v = p->stringProp(); + QVERIFY(v.isNull()); + QTEST(p->lastError().name(), "errorName"); +} + +void tst_QDBusAbstractInterface::directPropertyWriteErrors_data() +{ + callErrors_data(); +} + +void tst_QDBusAbstractInterface::directPropertyWriteErrors() +{ + QFETCH(QString, service); + QFETCH(QString, path); + Pinger p = getPinger(service, path); + QVERIFY2(p, "Not connected to D-Bus"); + + // we shouldn't be able to get this value: + // but there's no direct way of verifying that the setting failed + if (p->isValid()) + QCOMPARE(int(p->lastError().type()), int(QDBusError::NoError)); + p->setStringProp(""); + QTEST(p->lastError().name(), "errorName"); +} + +QTEST_MAIN(tst_QDBusAbstractInterface) +#include "tst_qdbusabstractinterface.moc" -- cgit v0.12 From 826c03c1c010a9d612007aa85ce3a5188edb0cb8 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 30 Jun 2009 19:27:16 +0200 Subject: Autotest: Add property-setting and getting tests to QDBusInterface --- tests/auto/qdbusinterface/tst_qdbusinterface.cpp | 102 ++++++++++++++++++++++- 1 file changed, 100 insertions(+), 2 deletions(-) diff --git a/tests/auto/qdbusinterface/tst_qdbusinterface.cpp b/tests/auto/qdbusinterface/tst_qdbusinterface.cpp index c4d4b08..718ba18 100644 --- a/tests/auto/qdbusinterface/tst_qdbusinterface.cpp +++ b/tests/auto/qdbusinterface/tst_qdbusinterface.cpp @@ -60,6 +60,9 @@ class MyObject: public QObject Q_CLASSINFO("D-Bus Introspection", "" " \n" " \n" +" \n" +" \n" +" \n" " \n" " \n" " \n" @@ -75,6 +78,9 @@ class MyObject: public QObject " \n" " \n" "") + Q_PROPERTY(int prop1 READ prop1 WRITE setProp1) + Q_PROPERTY(QList complexProp READ complexProp WRITE setComplexProp) + public: static int callCount; static QVariantList callArgs; @@ -84,6 +90,30 @@ public: subObject->setObjectName("subObject"); } + int m_prop1; + int prop1() const + { + ++callCount; + return m_prop1; + } + void setProp1(int value) + { + ++callCount; + m_prop1 = value; + } + + QList m_complexProp; + QList complexProp() const + { + ++callCount; + return m_complexProp; + } + void setComplexProp(const QList &value) + { + ++callCount; + m_complexProp = value; + } + public slots: void ping(QDBusMessage msg) @@ -146,6 +176,11 @@ private slots: void invokeMethod(); void signal(); + + void propertyRead(); + void propertyWrite(); + void complexPropertyRead(); + void complexPropertyWrite(); }; void tst_QDBusInterface::initTestCase() @@ -154,7 +189,7 @@ void tst_QDBusInterface::initTestCase() QVERIFY(con.isConnected()); QTest::qWait(500); - con.registerObject("/", &obj, QDBusConnection::ExportAdaptors + con.registerObject("/", &obj, QDBusConnection::ExportAllProperties | QDBusConnection::ExportAllSlots | QDBusConnection::ExportChildObjects); } @@ -231,8 +266,9 @@ void tst_QDBusInterface::introspect() QCOMPARE(mo->methodCount() - mo->methodOffset(), 3); QVERIFY(mo->indexOfSignal(TEST_SIGNAL_NAME "(QString)") != -1); - QCOMPARE(mo->propertyCount() - mo->propertyOffset(), 1); + QCOMPARE(mo->propertyCount() - mo->propertyOffset(), 2); QVERIFY(mo->indexOfProperty("prop1") != -1); + QVERIFY(mo->indexOfProperty("complexProp") != -1); } void tst_QDBusInterface::callMethod() @@ -322,6 +358,68 @@ void tst_QDBusInterface::signal() } } +void tst_QDBusInterface::propertyRead() +{ + QDBusConnection con = QDBusConnection::sessionBus(); + QDBusInterface iface(QDBusConnection::sessionBus().baseService(), QLatin1String("/"), + TEST_INTERFACE_NAME); + + int arg = obj.m_prop1 = 42; + MyObject::callCount = 0; + + QVariant v = iface.property("prop1"); + QVERIFY(v.isValid()); + QCOMPARE(v.userType(), int(QVariant::Int)); + QCOMPARE(v.toInt(), arg); + QCOMPARE(MyObject::callCount, 1); +} + +void tst_QDBusInterface::propertyWrite() +{ + QDBusConnection con = QDBusConnection::sessionBus(); + QDBusInterface iface(QDBusConnection::sessionBus().baseService(), QLatin1String("/"), + TEST_INTERFACE_NAME); + + int arg = 42; + obj.m_prop1 = 0; + MyObject::callCount = 0; + + QVERIFY(iface.setProperty("prop1", arg)); + QCOMPARE(MyObject::callCount, 1); + QCOMPARE(obj.m_prop1, arg); +} + +void tst_QDBusInterface::complexPropertyRead() +{ + QDBusConnection con = QDBusConnection::sessionBus(); + QDBusInterface iface(QDBusConnection::sessionBus().baseService(), QLatin1String("/"), + TEST_INTERFACE_NAME); + + QList arg = obj.m_complexProp = QList() << 42 << -47; + MyObject::callCount = 0; + + QVariant v = iface.property("complexProp"); + QVERIFY(v.isValid()); + QCOMPARE(v.userType(), qMetaTypeId >()); + QCOMPARE(v.value >(), arg); + QCOMPARE(MyObject::callCount, 1); +} + +void tst_QDBusInterface::complexPropertyWrite() +{ + QDBusConnection con = QDBusConnection::sessionBus(); + QDBusInterface iface(QDBusConnection::sessionBus().baseService(), QLatin1String("/"), + TEST_INTERFACE_NAME); + + QList arg = QList() << -47 << 42; + obj.m_complexProp.clear(); + MyObject::callCount = 0; + + QVERIFY(iface.setProperty("complexProp", qVariantFromValue(arg))); + QCOMPARE(MyObject::callCount, 1); + QCOMPARE(obj.m_complexProp, arg); +} + QTEST_MAIN(tst_QDBusInterface) #include "tst_qdbusinterface.moc" -- cgit v0.12 From 962b7fde5194a08a83609b9b4367425e52f76614 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 1 Jul 2009 17:44:56 +0200 Subject: Improve the code a bit more by using the variant that QMetaProperty creates. This works for the case of complex types that have to be demarshalled. We don't need to instantiate a new type because QMetaProperty has already done that for us. Also, fix the handling of properties of type variant. I have verified as well that the sending of those properties on the wire use a double-variant encoding (i.e., a variant containing a variant containing some data, the same that Qt 4.5 uses). It's a bit pedantic and it's hard to use when reading stuff, because you get a QVariant containing a QDBusVariant which contains data, but I can't change this anymore. Reviewed-By: Marius Bugge Monsen --- src/dbus/qdbusabstractinterface.cpp | 70 +++++++++++++++---------------------- src/dbus/qdbusabstractinterface_p.h | 2 +- 2 files changed, 29 insertions(+), 43 deletions(-) diff --git a/src/dbus/qdbusabstractinterface.cpp b/src/dbus/qdbusabstractinterface.cpp index 9bef2dd..7c520df 100644 --- a/src/dbus/qdbusabstractinterface.cpp +++ b/src/dbus/qdbusabstractinterface.cpp @@ -110,21 +110,17 @@ bool QDBusAbstractInterfacePrivate::canMakeCalls() const return true; } -QVariant QDBusAbstractInterfacePrivate::property(const QMetaProperty &mp) const +void QDBusAbstractInterfacePrivate::property(const QMetaProperty &mp, QVariant &where) const { - if (!isValid || !canMakeCalls()) // can't make calls - return QVariant(); + if (!isValid || !canMakeCalls()) { // can't make calls + where.clear(); + return; + } // is this metatype registered? - int mid; - const char *expectedSignature; - if (mp.type() == QVariant::LastType) { - // We're asking to read a QVariant - mid = qMetaTypeId(); - expectedSignature = "v"; - } else { - mid = QMetaType::type(mp.typeName()); - expectedSignature = QDBusMetaType::typeToSignature(mid); + const char *expectedSignature = ""; + if (mp.type() != 0xff) { + expectedSignature = QDBusMetaType::typeToSignature(where.userType()); if (expectedSignature == 0) { qWarning("QDBusAbstractInterface: type %s must be registered with QtDBus before it can be " "used to read property %s.%s", @@ -132,7 +128,8 @@ QVariant QDBusAbstractInterfacePrivate::property(const QMetaProperty &mp) const lastError = QDBusError(QDBusError::Failed, QString::fromLatin1("Unregistered type %1 cannot be handled") .arg(QLatin1String(mp.typeName()))); - return QVariant(); + where.clear(); + return; } } @@ -146,21 +143,27 @@ QVariant QDBusAbstractInterfacePrivate::property(const QMetaProperty &mp) const if (reply.type() != QDBusMessage::ReplyMessage) { lastError = reply; - return QVariant(); + where.clear(); + return; } if (reply.signature() != QLatin1String("v")) { QString errmsg = QLatin1String("Invalid signature `%1' in return from call to " DBUS_INTERFACE_PROPERTIES); lastError = QDBusError(QDBusError::InvalidSignature, errmsg.arg(reply.signature())); - return QVariant(); + where.clear(); + return; } QByteArray foundSignature; const char *foundType = 0; QVariant value = qvariant_cast(reply.arguments().at(0)).variant(); - if (value.userType() == mid) - return value; // simple match + if (value.userType() == where.userType() || mp.type() == 0xff + || (expectedSignature[0] == 'v' && expectedSignature[1] == '\0')) { + // simple match + where = value; + return; + } if (value.userType() == qMetaTypeId()) { QDBusArgument arg = qvariant_cast(value); @@ -168,14 +171,9 @@ QVariant QDBusAbstractInterfacePrivate::property(const QMetaProperty &mp) const foundType = "user type"; foundSignature = arg.currentSignature().toLatin1(); if (foundSignature == expectedSignature) { - void *null = 0; - QVariant result(mid, null); - QDBusMetaType::demarshall(arg, mid, result.data()); - - if (mp.type() == QVariant::LastType) - // special case: QVariant - return qvariant_cast(result).variant(); - return result; + // signatures match, we can demarshall + QDBusMetaType::demarshall(arg, where.userType(), where.data()); + return; } } else { foundType = value.typeName(); @@ -192,7 +190,8 @@ QVariant QDBusAbstractInterfacePrivate::property(const QMetaProperty &mp) const QString::fromUtf8(mp.name()), QString::fromLatin1(mp.typeName()), QString::fromLatin1(expectedSignature))); - return QVariant(); + where.clear(); + return; } bool QDBusAbstractInterfacePrivate::setProperty(const QMetaProperty &mp, const QVariant &value) @@ -246,7 +245,7 @@ int QDBusAbstractInterfaceBase::qt_metacall(QMetaObject::Call _c, int _id, void if (_c == QMetaObject::WriteProperty) { status = d_func()->setProperty(mp, variant) ? 1 : 0; } else { - variant = d_func()->property(mp); + d_func()->property(mp, variant); status = variant.isValid() ? 1 : 0; } _id = -1; @@ -576,11 +575,7 @@ QVariant QDBusAbstractInterface::internalPropGet(const char *propname) const // assume this property exists and is readable // we're only called from generated code anyways - int idx = metaObject()->indexOfProperty(propname); - if (idx != -1) - return d_func()->property(metaObject()->property(idx)); - qWarning("QDBusAbstractInterface::internalPropGet called with unknown property '%s'", propname); - return QVariant(); // error + return property(propname); } /*! @@ -589,16 +584,7 @@ QVariant QDBusAbstractInterface::internalPropGet(const char *propname) const */ void QDBusAbstractInterface::internalPropSet(const char *propname, const QVariant &value) { - Q_D(QDBusAbstractInterface); - - // assume this property exists and is writeable - // we're only called from generated code anyways - - int idx = metaObject()->indexOfProperty(propname); - if (idx != -1) - d->setProperty(metaObject()->property(idx), value); - else - qWarning("QDBusAbstractInterface::internalPropGet called with unknown property '%s'", propname); + setProperty(propname, value); } /*! diff --git a/src/dbus/qdbusabstractinterface_p.h b/src/dbus/qdbusabstractinterface_p.h index e577898..65df902 100644 --- a/src/dbus/qdbusabstractinterface_p.h +++ b/src/dbus/qdbusabstractinterface_p.h @@ -86,7 +86,7 @@ public: bool canMakeCalls() const; // these functions do not check if the property is valid - QVariant property(const QMetaProperty &mp) const; + void property(const QMetaProperty &mp, QVariant &where) const; bool setProperty(const QMetaProperty &mp, const QVariant &value); // return conn's d pointer -- cgit v0.12 From 43a760280edd49382d01eb1e23ae2a08933b6bf7 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 1 Jul 2009 17:45:17 +0200 Subject: Autotest: add tests for checking variant properties --- .../com.trolltech.QtDBus.Pinger.xml | 1 + tests/auto/qdbusabstractinterface/interface.h | 4 ++ tests/auto/qdbusabstractinterface/pinger.h | 10 ++++- .../tst_qdbusabstractinterface.cpp | 47 ++++++++++++++++++++++ 4 files changed, 60 insertions(+), 2 deletions(-) diff --git a/tests/auto/qdbusabstractinterface/com.trolltech.QtDBus.Pinger.xml b/tests/auto/qdbusabstractinterface/com.trolltech.QtDBus.Pinger.xml index 8909675..fb2aab8 100644 --- a/tests/auto/qdbusabstractinterface/com.trolltech.QtDBus.Pinger.xml +++ b/tests/auto/qdbusabstractinterface/com.trolltech.QtDBus.Pinger.xml @@ -2,6 +2,7 @@ + diff --git a/tests/auto/qdbusabstractinterface/interface.h b/tests/auto/qdbusabstractinterface/interface.h index 86e0dc4..f6d34a7 100644 --- a/tests/auto/qdbusabstractinterface/interface.h +++ b/tests/auto/qdbusabstractinterface/interface.h @@ -80,10 +80,12 @@ class Interface: public QObject Q_OBJECT Q_CLASSINFO("D-Bus Interface", "com.trolltech.QtDBus.Pinger") Q_PROPERTY(QString stringProp READ stringProp WRITE setStringProp SCRIPTABLE true) + Q_PROPERTY(QDBusVariant variantProp READ variantProp WRITE setVariantProp SCRIPTABLE true) Q_PROPERTY(RegisteredType complexProp READ complexProp WRITE setComplexProp SCRIPTABLE true) friend class tst_QDBusAbstractInterface; QString m_stringProp; + QDBusVariant m_variantProp; RegisteredType m_complexProp; public: @@ -91,6 +93,8 @@ public: QString stringProp() const { return m_stringProp; } void setStringProp(const QString &s) { m_stringProp = s; } + QDBusVariant variantProp() const { return m_variantProp; } + void setVariantProp(const QDBusVariant &v) { m_variantProp = v; } RegisteredType complexProp() const { return m_complexProp; } void setComplexProp(const RegisteredType &r) { m_complexProp = r; } diff --git a/tests/auto/qdbusabstractinterface/pinger.h b/tests/auto/qdbusabstractinterface/pinger.h index 3ff218c..6e92e65 100644 --- a/tests/auto/qdbusabstractinterface/pinger.h +++ b/tests/auto/qdbusabstractinterface/pinger.h @@ -49,8 +49,8 @@ * Do not edit! All changes made to it will be lost. */ -#ifndef PINGER_H_1246371899 -#define PINGER_H_1246371899 +#ifndef PINGER_H_1246460303 +#define PINGER_H_1246460303 #include #include @@ -89,6 +89,12 @@ public: inline void setStringProp(const QString &value) { internalPropSet("stringProp", qVariantFromValue(value)); } + Q_PROPERTY(QDBusVariant variantProp READ variantProp WRITE setVariantProp) + inline QDBusVariant variantProp() const + { return qvariant_cast< QDBusVariant >(internalPropGet("variantProp")); } + inline void setVariantProp(const QDBusVariant &value) + { internalPropSet("variantProp", qVariantFromValue(value)); } + public Q_SLOTS: // METHODS inline QDBusPendingReply complexMethod() { diff --git a/tests/auto/qdbusabstractinterface/tst_qdbusabstractinterface.cpp b/tests/auto/qdbusabstractinterface/tst_qdbusabstractinterface.cpp index 4aee089..fa5e332 100644 --- a/tests/auto/qdbusabstractinterface/tst_qdbusabstractinterface.cpp +++ b/tests/auto/qdbusabstractinterface/tst_qdbusabstractinterface.cpp @@ -84,11 +84,15 @@ private slots: void stringPropRead(); void stringPropWrite(); + void variantPropRead(); + void variantPropWrite(); void complexPropRead(); void complexPropWrite(); void stringPropDirectRead(); void stringPropDirectWrite(); + void variantPropDirectRead(); + void variantPropDirectWrite(); void complexPropDirectRead(); void complexPropDirectWrite(); @@ -242,6 +246,29 @@ void tst_QDBusAbstractInterface::stringPropWrite() QCOMPARE(targetObj.m_stringProp, expectedValue); } +void tst_QDBusAbstractInterface::variantPropRead() +{ + Pinger p = getPinger(); + QVERIFY2(p, "Not connected to D-Bus"); + + QDBusVariant expectedValue = targetObj.m_variantProp = QDBusVariant(QVariant(42)); + QVariant v = p->property("variantProp"); + QVERIFY(v.isValid()); + QDBusVariant value = v.value(); + QCOMPARE(value.variant().userType(), expectedValue.variant().userType()); + QCOMPARE(value.variant(), expectedValue.variant()); +} + +void tst_QDBusAbstractInterface::variantPropWrite() +{ + Pinger p = getPinger(); + QVERIFY2(p, "Not connected to D-Bus"); + + QDBusVariant expectedValue = QDBusVariant(Q_INT64_C(-47)); + QVERIFY(p->setProperty("variantProp", qVariantFromValue(expectedValue))); + QCOMPARE(targetObj.m_variantProp.variant(), expectedValue.variant()); +} + void tst_QDBusAbstractInterface::complexPropRead() { Pinger p = getPinger(); @@ -282,6 +309,26 @@ void tst_QDBusAbstractInterface::stringPropDirectWrite() QCOMPARE(targetObj.m_stringProp, expectedValue); } +void tst_QDBusAbstractInterface::variantPropDirectRead() +{ + Pinger p = getPinger(); + QVERIFY2(p, "Not connected to D-Bus"); + + QDBusVariant expectedValue = targetObj.m_variantProp = QDBusVariant(42); + QCOMPARE(p->variantProp().variant(), expectedValue.variant()); +} + +void tst_QDBusAbstractInterface::variantPropDirectWrite() +{ + Pinger p = getPinger(); + QVERIFY2(p, "Not connected to D-Bus"); + + QDBusVariant expectedValue = QDBusVariant(Q_INT64_C(-47)); + p->setVariantProp(expectedValue); + QCOMPARE(targetObj.m_variantProp.variant().userType(), expectedValue.variant().userType()); + QCOMPARE(targetObj.m_variantProp.variant(), expectedValue.variant()); +} + void tst_QDBusAbstractInterface::complexPropDirectRead() { Pinger p = getPinger(); -- cgit v0.12 From 232f7af78d152518ccdcaaf1f42f89abb048ae5f Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 1 Jul 2009 17:52:48 +0200 Subject: Replace internalPropGet and internalPropSet with the QObject versions in QDBusAbstractInterface. They're now good enough and as fast. Reviewed-By: Marius Bugge Monsen --- tests/auto/qdbusabstractinterface/pinger.h | 16 ++++++++-------- tools/qdbus/qdbusxml2cpp/qdbusxml2cpp.cpp | 11 ++++------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/tests/auto/qdbusabstractinterface/pinger.h b/tests/auto/qdbusabstractinterface/pinger.h index 6e92e65..fb8adda 100644 --- a/tests/auto/qdbusabstractinterface/pinger.h +++ b/tests/auto/qdbusabstractinterface/pinger.h @@ -49,8 +49,8 @@ * Do not edit! All changes made to it will be lost. */ -#ifndef PINGER_H_1246460303 -#define PINGER_H_1246460303 +#ifndef PINGER_H_1246463415 +#define PINGER_H_1246463415 #include #include @@ -79,21 +79,21 @@ public: Q_PROPERTY(RegisteredType complexProp READ complexProp WRITE setComplexProp) inline RegisteredType complexProp() const - { return qvariant_cast< RegisteredType >(internalPropGet("complexProp")); } + { return qvariant_cast< RegisteredType >(property("complexProp")); } inline void setComplexProp(RegisteredType value) - { internalPropSet("complexProp", qVariantFromValue(value)); } + { setProperty("complexProp", qVariantFromValue(value)); } Q_PROPERTY(QString stringProp READ stringProp WRITE setStringProp) inline QString stringProp() const - { return qvariant_cast< QString >(internalPropGet("stringProp")); } + { return qvariant_cast< QString >(property("stringProp")); } inline void setStringProp(const QString &value) - { internalPropSet("stringProp", qVariantFromValue(value)); } + { setProperty("stringProp", qVariantFromValue(value)); } Q_PROPERTY(QDBusVariant variantProp READ variantProp WRITE setVariantProp) inline QDBusVariant variantProp() const - { return qvariant_cast< QDBusVariant >(internalPropGet("variantProp")); } + { return qvariant_cast< QDBusVariant >(property("variantProp")); } inline void setVariantProp(const QDBusVariant &value) - { internalPropSet("variantProp", qVariantFromValue(value)); } + { setProperty("variantProp", qVariantFromValue(value)); } public Q_SLOTS: // METHODS inline QDBusPendingReply complexMethod() diff --git a/tools/qdbus/qdbusxml2cpp/qdbusxml2cpp.cpp b/tools/qdbus/qdbusxml2cpp/qdbusxml2cpp.cpp index 5d1ac32..b8b9338 100644 --- a/tools/qdbus/qdbusxml2cpp/qdbusxml2cpp.cpp +++ b/tools/qdbus/qdbusxml2cpp/qdbusxml2cpp.cpp @@ -613,18 +613,15 @@ static void writeProxy(const QString &filename, const QDBusIntrospection::Interf // getter: if (property.access != QDBusIntrospection::Property::Write) { - hs << " inline " << type << " " << getter << "() const" << endl; - if (type != "QVariant") - hs << " { return qvariant_cast< " << type << " >(internalPropGet(\"" - << property.name << "\")); }" << endl; - else - hs << " { return internalPropGet(\"" << property.name << "\"); }" << endl; + hs << " inline " << type << " " << getter << "() const" << endl + << " { return qvariant_cast< " << type << " >(property(\"" + << property.name << "\")); }" << endl; } // setter: if (property.access != QDBusIntrospection::Property::Read) { hs << " inline void " << setter << "(" << constRefArg(type) << "value)" << endl - << " { internalPropSet(\"" << property.name + << " { setProperty(\"" << property.name << "\", qVariantFromValue(value)); }" << endl; } -- cgit v0.12 From 200286b8e83918e785b61e4695443a3b77ebeaea Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 1 Jul 2009 18:24:56 +0200 Subject: Implement a support for getting return arguments out of invokeMethod with QDBusInterface. The problem was that I didn't know how to implement the operator= for all types. But it turns out that this was possible all along: the only types I have to implement the operator= for are the basic types, which are already demarshalled. The complex types are left in QDBusArgument semi-demarshalling, but we have QDBusMetaType::demarshall, which takes a void* to an already-constructed type and demarshalls into it. That's exactly what the doctor ordered. Task-number: 206765 Reviewed-By: Marius Bugge Monsen --- src/dbus/qdbusinterface.cpp | 126 +++++++++++++++++++++-- tests/auto/qdbusinterface/tst_qdbusinterface.cpp | 92 ++++++++++++++++- 2 files changed, 209 insertions(+), 9 deletions(-) diff --git a/src/dbus/qdbusinterface.cpp b/src/dbus/qdbusinterface.cpp index 6f61847..5f6df0a 100644 --- a/src/dbus/qdbusinterface.cpp +++ b/src/dbus/qdbusinterface.cpp @@ -51,6 +51,102 @@ QT_BEGIN_NAMESPACE +static void copyArgument(void *to, int id, const QVariant &arg) +{ + if (id == arg.userType()) { + switch (id) { + case QVariant::Bool: + *reinterpret_cast(to) = arg.toBool(); + return; + + case QMetaType::UChar: + *reinterpret_cast(to) = arg.value(); + return; + + case QMetaType::Short: + *reinterpret_cast(to) = arg.value(); + return; + + case QMetaType::UShort: + *reinterpret_cast(to) = arg.value(); + return; + + case QVariant::Int: + *reinterpret_cast(to) = arg.toInt(); + return; + + case QVariant::UInt: + *reinterpret_cast(to) = arg.toUInt(); + return; + + case QVariant::LongLong: + *reinterpret_cast(to) = arg.toLongLong(); + return; + + case QVariant::ULongLong: + *reinterpret_cast(to) = arg.toULongLong(); + return; + + case QVariant::Double: + *reinterpret_cast(to) = arg.toDouble(); + return; + + case QVariant::String: + *reinterpret_cast(to) = arg.toString(); + return; + + case QVariant::ByteArray: + *reinterpret_cast(to) = arg.toByteArray(); + return; + + case QVariant::StringList: + *reinterpret_cast(to) = arg.toStringList(); + return; + } + + if (id == QDBusMetaTypeId::variant) { + *reinterpret_cast(to) = arg.value(); + return; + } else if (id == QDBusMetaTypeId::objectpath) { + *reinterpret_cast(to) = arg.value(); + return; + } else if (id == QDBusMetaTypeId::signature) { + *reinterpret_cast(to) = arg.value(); + return; + } + + // those above are the only types possible + // the demarshaller code doesn't demarshall anything else + qFatal("Found a decoded basic type in a D-Bus reply that shouldn't be there"); + } + + // if we got here, it's either an un-dermarshalled type or a mismatch + if (arg.userType() != QDBusMetaTypeId::argument) { + // it's a mismatch + //qWarning? + return; + } + + // is this type registered? + const char *userSignature = QDBusMetaType::typeToSignature(id); + if (!userSignature || !*userSignature) { + // type not registered + //qWarning? + return; + } + + // is it the same signature? + QDBusArgument dbarg = arg.value(); + if (dbarg.currentSignature() != QLatin1String(userSignature)) { + // not the same signature, another mismatch + //qWarning? + return; + } + + // we can demarshall + QDBusMetaType::demarshall(dbarg, id, to); +} + QDBusInterfacePrivate::QDBusInterfacePrivate(const QString &serv, const QString &p, const QString &iface, const QDBusConnection &con) : QDBusAbstractInterfacePrivate(serv, p, iface, con, true), metaObject(0) @@ -186,23 +282,37 @@ int QDBusInterfacePrivate::metacall(QMetaObject::Call c, int id, void **argv) // we will assume that the input arguments were passed correctly QVariantList args; - for (int i = 1; i <= inputTypesCount; ++i) + int i = 1; + for ( ; i <= inputTypesCount; ++i) args << QVariant(inputTypes[i], argv[i]); // make the call - QPointer qq = q; QDBusMessage reply = q->callWithArgumentList(QDBus::Block, methodName, args); - args.clear(); - // we ignore return values + if (reply.type() == QDBusMessage::ReplyMessage) { + // attempt to demarshall the return values + args = reply.arguments(); + QVariantList::ConstIterator it = args.constBegin(); + const int *outputTypes = metaObject->outputTypesForMethod(id); + int outputTypesCount = *outputTypes++; + + if (*mm.typeName()) { + // this method has a return type + if (argv[0] && it != args.constEnd()) + copyArgument(argv[0], *outputTypes++, *it); - // access to "this" or to "q" below this point must check for "qq" - // we may have been deleted! + // skip this argument even if we didn't copy it + --outputTypesCount; + ++it; + } - if (!qq.isNull()) - lastError = reply; + for (int j = 0; j < outputTypesCount && it != args.constEnd(); ++i, ++j, ++it) { + copyArgument(argv[i], outputTypes[j], *it); + } + } // done + lastError = reply; return -1; } } diff --git a/tests/auto/qdbusinterface/tst_qdbusinterface.cpp b/tests/auto/qdbusinterface/tst_qdbusinterface.cpp index 718ba18..60afe4e 100644 --- a/tests/auto/qdbusinterface/tst_qdbusinterface.cpp +++ b/tests/auto/qdbusinterface/tst_qdbusinterface.cpp @@ -76,6 +76,12 @@ class MyObject: public QObject " \n" " \n" " \n" +" \n" +" \n" +" \n" +" \n" +" \n" +" \n" " \n" "") Q_PROPERTY(int prop1 READ prop1 WRITE setProp1) @@ -174,6 +180,9 @@ private slots: void introspect(); void callMethod(); void invokeMethod(); + void invokeMethodWithReturn(); + void invokeMethodWithMultiReturn(); + void invokeMethodWithComplexReturn(); void signal(); @@ -263,7 +272,7 @@ void tst_QDBusInterface::introspect() const QMetaObject *mo = iface.metaObject(); - QCOMPARE(mo->methodCount() - mo->methodOffset(), 3); + QCOMPARE(mo->methodCount() - mo->methodOffset(), 4); QVERIFY(mo->indexOfSignal(TEST_SIGNAL_NAME "(QString)") != -1); QCOMPARE(mo->propertyCount() - mo->propertyOffset(), 2); @@ -317,6 +326,87 @@ void tst_QDBusInterface::invokeMethod() QCOMPARE(dv.variant().toString(), QString("foo")); } +void tst_QDBusInterface::invokeMethodWithReturn() +{ + QDBusConnection con = QDBusConnection::sessionBus(); + QDBusInterface iface(QDBusConnection::sessionBus().baseService(), QLatin1String("/"), + TEST_INTERFACE_NAME); + + // make the call without a return type + MyObject::callCount = 0; + QDBusVariant arg("foo"); + QDBusVariant retArg; + QVERIFY(QMetaObject::invokeMethod(&iface, "ping", Q_RETURN_ARG(QDBusVariant, retArg), Q_ARG(QDBusVariant, arg))); + QCOMPARE(MyObject::callCount, 1); + + // verify what the callee received + QCOMPARE(MyObject::callArgs.count(), 1); + QVariant v = MyObject::callArgs.at(0); + QDBusVariant dv = qdbus_cast(v); + QCOMPARE(dv.variant().type(), QVariant::String); + QCOMPARE(dv.variant().toString(), arg.variant().toString()); + + // verify that we got the reply as expected + QCOMPARE(retArg.variant(), arg.variant()); +} + +void tst_QDBusInterface::invokeMethodWithMultiReturn() +{ + QDBusConnection con = QDBusConnection::sessionBus(); + QDBusInterface iface(QDBusConnection::sessionBus().baseService(), QLatin1String("/"), + TEST_INTERFACE_NAME); + + // make the call without a return type + MyObject::callCount = 0; + QDBusVariant arg("foo"), arg2("bar"); + QDBusVariant retArg, retArg2; + QVERIFY(QMetaObject::invokeMethod(&iface, "ping", + Q_RETURN_ARG(QDBusVariant, retArg), + Q_ARG(QDBusVariant, arg), + Q_ARG(QDBusVariant, arg2), + Q_ARG(QDBusVariant&, retArg2))); + QCOMPARE(MyObject::callCount, 1); + + // verify what the callee received + QCOMPARE(MyObject::callArgs.count(), 2); + QVariant v = MyObject::callArgs.at(0); + QDBusVariant dv = qdbus_cast(v); + QCOMPARE(dv.variant().type(), QVariant::String); + QCOMPARE(dv.variant().toString(), arg.variant().toString()); + + v = MyObject::callArgs.at(1); + dv = qdbus_cast(v); + QCOMPARE(dv.variant().type(), QVariant::String); + QCOMPARE(dv.variant().toString(), arg2.variant().toString()); + + // verify that we got the replies as expected + QCOMPARE(retArg.variant(), arg.variant()); + QCOMPARE(retArg2.variant(), arg2.variant()); +} + +void tst_QDBusInterface::invokeMethodWithComplexReturn() +{ + QDBusConnection con = QDBusConnection::sessionBus(); + QDBusInterface iface(QDBusConnection::sessionBus().baseService(), QLatin1String("/"), + TEST_INTERFACE_NAME); + + // make the call without a return type + MyObject::callCount = 0; + QList arg = QList() << 42 << -47; + QList retArg; + QVERIFY(QMetaObject::invokeMethod(&iface, "ping", Q_RETURN_ARG(QList, retArg), Q_ARG(QList, arg))); + QCOMPARE(MyObject::callCount, 1); + + // verify what the callee received + QCOMPARE(MyObject::callArgs.count(), 1); + QVariant v = MyObject::callArgs.at(0); + QCOMPARE(v.userType(), qMetaTypeId()); + QCOMPARE(qdbus_cast >(v), arg); + + // verify that we got the reply as expected + QCOMPARE(retArg, arg); +} + void tst_QDBusInterface::signal() { QDBusConnection con = QDBusConnection::sessionBus(); -- cgit v0.12 From 9a90dab23bd1bd37bd4a7aace588896d2ae7e9d9 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 1 Jul 2009 10:53:23 +0200 Subject: add support for attaching meta data to translatable messages Requirement: QT-457 --- .../snippets/code/src_corelib_kernel_qobject.cpp | 9 ++++++ src/corelib/kernel/qobject.cpp | 28 +++++++++++++++++ .../lupdate/testdata/good/parsecpp/main.cpp | 19 ++++++++++++ .../testdata/good/parsecpp/project.ts.result | 21 +++++++++++++ tools/linguist/lupdate/cpp.cpp | 35 ++++++++++++++++++---- 5 files changed, 107 insertions(+), 5 deletions(-) diff --git a/doc/src/snippets/code/src_corelib_kernel_qobject.cpp b/doc/src/snippets/code/src_corelib_kernel_qobject.cpp index 5a7c5a7..5c0f80c 100644 --- a/doc/src/snippets/code/src_corelib_kernel_qobject.cpp +++ b/doc/src/snippets/code/src_corelib_kernel_qobject.cpp @@ -376,6 +376,15 @@ hostNameLabel->setText(tr("Name:")); QString example = tr("Example"); //! [40] +//! [meta data] +//: This is a comment for the translator. +//= qtn_foo_bar +//~ loc-layout_id foo_dialog +//~ loc-blank False +//~ magic-stuff This might mean something magic. +QString text = MyMagicClass::tr("Sim sala bim."); +//! [meta data] + //! [explicit tr context] QString text = QScrollBar::tr("Page up"); //! [explicit tr context] diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 9dc25c7..9e87b3b 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -2086,6 +2086,34 @@ void QObject::deleteLater() \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 17 + \section1 Meta Data + + Additional data can be attached to each translatable message. + The syntax: + + \tt{//= } + + can be used to give the message a unique identifier to support tools + which need it. + The syntax: + + \tt{//~ } + + can be used to attach meta data to the message. The field name should consist + of a domain prefix (possibly the conventional file extension of the file format + the field is inspired by), a hyphen and the actual field name in + underscore-delimited notation. For storage in TS files, the field name together + with the prefix "extra-" will form an XML element name. The field contents will + be XML-escaped, but otherwise appear verbatim as the element's contents. + Any number of unique fields can be added to each message. + + Example: + + \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp meta data + + Meta data appearing right in front of a magic TRANSLATOR comment applies to the + whole TS file. + \section1 Character Encodings You can set the encoding for \a sourceText by calling QTextCodec::setCodecForTr(). diff --git a/tests/auto/linguist/lupdate/testdata/good/parsecpp/main.cpp b/tests/auto/linguist/lupdate/testdata/good/parsecpp/main.cpp index df75baf..9fb43fe 100644 --- a/tests/auto/linguist/lupdate/testdata/good/parsecpp/main.cpp +++ b/tests/auto/linguist/lupdate/testdata/good/parsecpp/main.cpp @@ -156,3 +156,22 @@ QT_TRANSLATE_NOOP3_UTF8("scope", "string", "comment") // 4.4 doesn't see this QT_TRANSLATE_NOOP("scope", "string " // this is an interleaved comment "continuation on next line") + + +class TestingTake17 : QObject { + Q_OBJECT + + int function(void) + { + //: random comment + //= this_is_an_id + //~ loc-layout_id fooish_bar + //~ po-ignore_me totally foo-barred nonsense + tr("something cool"); + + tr("less cool"); + + //= another_id + tr("even more cool"); + } +}; diff --git a/tests/auto/linguist/lupdate/testdata/good/parsecpp/project.ts.result b/tests/auto/linguist/lupdate/testdata/good/parsecpp/project.ts.result index 9386c19..5bd7525 100644 --- a/tests/auto/linguist/lupdate/testdata/good/parsecpp/project.ts.result +++ b/tests/auto/linguist/lupdate/testdata/good/parsecpp/project.ts.result @@ -239,6 +239,27 @@ + TestingTake17 + + + something cool + random comment + + totally foo-barred nonsense + fooish_bar + + + + less cool + + + + + even more cool + + + + scope diff --git a/tools/linguist/lupdate/cpp.cpp b/tools/linguist/lupdate/cpp.cpp index 09148e7..b1d2d01 100644 --- a/tools/linguist/lupdate/cpp.cpp +++ b/tools/linguist/lupdate/cpp.cpp @@ -180,7 +180,8 @@ private: QString transcode(const QString &str, bool utf8); void recordMessage( int line, const QString &context, const QString &text, const QString &comment, - const QString &extracomment, bool utf8, bool plural); + const QString &extracomment, const QString &msgid, const TranslatorMessage::ExtraData &extra, + bool utf8, bool plural); void processInclude(const QString &file, ConversionData &cd, QSet &inclusions); @@ -1299,13 +1300,16 @@ QString CppParser::transcode(const QString &str, bool utf8) void CppParser::recordMessage( int line, const QString &context, const QString &text, const QString &comment, - const QString &extracomment, bool utf8, bool plural) + const QString &extracomment, const QString &msgid, const TranslatorMessage::ExtraData &extra, + bool utf8, bool plural) { TranslatorMessage msg( transcode(context, utf8), transcode(text, utf8), transcode(comment, utf8), QString(), yyFileName, line, QStringList(), TranslatorMessage::Unfinished, plural); msg.setExtraComment(transcode(extracomment.simplified(), utf8)); + msg.setId(msgid); + msg.setExtras(extra); if ((utf8 || yyForceUtf8) && !yyCodecIsUtf8 && msg.needs8Bit()) msg.setUtf8(true); results->tor->append(msg); @@ -1332,6 +1336,8 @@ void CppParser::parseInternal(ConversionData &cd, QSet &inclusions) QString text; QString comment; QString extracomment; + QString msgid; + TranslatorMessage::ExtraData extra; QString prefix; #ifdef DIAGNOSE_RETRANSLATABILITY QString functionName; @@ -1604,9 +1610,11 @@ void CppParser::parseInternal(ConversionData &cd, QSet &inclusions) prefix.clear(); } - recordMessage(line, context, text, comment, extracomment, utf8, plural); + recordMessage(line, context, text, comment, extracomment, msgid, extra, utf8, plural); } extracomment.clear(); + msgid.clear(); + extra.clear(); break; case Tok_translateUtf8: case Tok_translate: @@ -1655,9 +1663,11 @@ void CppParser::parseInternal(ConversionData &cd, QSet &inclusions) break; } } - recordMessage(line, context, text, comment, extracomment, utf8, plural); + recordMessage(line, context, text, comment, extracomment, msgid, extra, utf8, plural); } extracomment.clear(); + msgid.clear(); + extra.clear(); break; case Tok_Q_DECLARE_TR_FUNCTIONS: case Tok_Q_OBJECT: @@ -1679,6 +1689,15 @@ void CppParser::parseInternal(ConversionData &cd, QSet &inclusions) if (yyComment.startsWith(QLatin1Char(':'))) { yyComment.remove(0, 1); extracomment.append(yyComment); + } else if (yyComment.startsWith(QLatin1Char('='))) { + yyComment.remove(0, 1); + msgid = yyComment.simplified(); + } else if (yyComment.startsWith(QLatin1Char('~'))) { + yyComment.remove(0, 1); + yyComment = yyComment.trimmed(); + int k = yyComment.indexOf(QLatin1Char(' ')); + if (k > -1) + extra.insert(yyComment.left(k), yyComment.mid(k + 1).trimmed()); } else { comment = yyComment.simplified(); if (comment.startsWith(QLatin1String(MagicComment))) { @@ -1689,7 +1708,11 @@ void CppParser::parseInternal(ConversionData &cd, QSet &inclusions) } else { context = comment.left(k); comment.remove(0, k + 1); - recordMessage(yyLineNo, context, QString(), comment, extracomment, false, false); + recordMessage(yyLineNo, context, QString(), comment, extracomment, + QString(), TranslatorMessage::ExtraData(), false, false); + extracomment.clear(); + results->tor->setExtras(extra); + extra.clear(); } } } @@ -1739,6 +1762,8 @@ void CppParser::parseInternal(ConversionData &cd, QSet &inclusions) prospectiveContext.clear(); prefix.clear(); extracomment.clear(); + msgid.clear(); + extra.clear(); yyTokColonSeen = false; yyTok = getToken(); break; -- cgit v0.12 From ebfdbff7712e230c19fc2a990632038e3fc79ef2 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 2 Jul 2009 13:27:21 +0200 Subject: Doc: indicate that these methods are added in 4.6 --- src/dbus/qdbuspendingcall.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/dbus/qdbuspendingcall.cpp b/src/dbus/qdbuspendingcall.cpp index 7807543..0ec1a26 100644 --- a/src/dbus/qdbuspendingcall.cpp +++ b/src/dbus/qdbuspendingcall.cpp @@ -410,6 +410,7 @@ bool QDBusPendingCall::setReplyCallback(QObject *target, const char *member) #endif /*! + \since 4.6 Creates a QDBusPendingCall object based on the error condition \a error. The resulting pending call object will be in the "finished" state and QDBusPendingReply::isError() will return true. @@ -422,6 +423,7 @@ QDBusPendingCall QDBusPendingCall::fromError(const QDBusError &error) } /*! + \since 4.6 Creates a QDBusPendingCall object based on the message \a msg. The message must be of type QDBusMessage::ErrorMessage or QDBusMessage::ReplyMessage (that is, a message that is typical -- cgit v0.12 From c5f83fbd89d6bb950fb012c285879f6c88b5bdf3 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 22 Apr 2009 16:47:12 +0200 Subject: Add qcore_unix_p.h containing mostly safe versions of Unix functions. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Most of these functions are from unistd.h and need to have a loop around the actual call because the calls can be interrupted by a signal delivery. Some special calls (open, dup2, pipe) require an extra flag to support thread-safe execution: the file descriptor must be created from the operating system with the FD_CLOEXEC flag already set. The O_CLOEXEC flag is specified in POSIX.1-2008, but the rest is Linux-specific. Reviewed-By: João Abecasis --- src/corelib/kernel/kernel.pri | 1 + src/corelib/kernel/qcore_unix_p.h | 246 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 247 insertions(+) create mode 100644 src/corelib/kernel/qcore_unix_p.h diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri index ecef555..6f28029 100644 --- a/src/corelib/kernel/kernel.pri +++ b/src/corelib/kernel/kernel.pri @@ -92,6 +92,7 @@ unix { kernel/qsharedmemory_unix.cpp \ kernel/qsystemsemaphore_unix.cpp HEADERS += \ + kernel/qcore_unix_p.h \ kernel/qcrashhandler_p.h contains(QT_CONFIG, glib) { diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h new file mode 100644 index 0000000..4e3158a --- /dev/null +++ b/src/corelib/kernel/qcore_unix_p.h @@ -0,0 +1,246 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCORE_UNIX_P_H +#define QCORE_UNIX_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of Qt code on Unix. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qplatformdefs.h" + +#ifndef Q_OS_UNIX +# error "qcore_unix_p.h included on a non-Unix system" +#endif + +#include +#include +#include + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +#if defined(Q_OS_LINUX) && defined(__GLIBC__) && (__GLIBC__ * 0x100 + __GLIBC_MINOR__) >= 0x0209 +# define QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC 1 +#else +# define QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC 0 +#endif + +#define EINTR_LOOP(var, cmd) \ + do { \ + var = cmd; \ + } while (var == -1 && errno == EINTR) + + +// don't call QT_OPEN or ::open +// call qt_safe_open +static inline int qt_safe_open(const char *pathname, int flags, mode_t mode = 0777) +{ +#ifdef O_CLOEXEC + flags |= O_CLOEXEC; +#endif + register int fd; + EINTR_LOOP(fd, QT_OPEN(pathname, flags, mode)); + + // unknown flags are ignored, so we have no way of verifying if + // O_CLOEXEC was accepted + if (fd != -1) + ::fcntl(fd, F_SETFD, FD_CLOEXEC); + return fd; +} +#undef QT_OPEN +#define QT_OPEN qt_safe_open + +// don't call ::pipe +// call qt_safe_pipe +static inline int qt_safe_pipe(int pipefd[2], int flags = 0) +{ +#ifdef O_CLOEXEC + Q_ASSERT((flags & ~(O_CLOEXEC | O_NONBLOCK)) == 0); +#else + Q_ASSERT((flags & ~O_NONBLOCK) == 0); +#endif + + register int ret; +#if QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC + // use pipe2 + flags |= O_CLOEXEC; + ret = ::pipe2(pipefd, flags); // pipe2 is Linux-specific and is documented not to return EINTR + if (ret == 0 || errno != ENOSYS) + return ret; +#endif + + ret = ::pipe(pipefd); + if (ret == -1) + return -1; + + ::fcntl(pipefd[0], F_SETFD, FD_CLOEXEC); + ::fcntl(pipefd[1], F_SETFD, FD_CLOEXEC); + + // set non-block too? + if (flags & O_NONBLOCK) { + ::fcntl(pipefd[0], F_SETFL, ::fcntl(pipefd[0], F_GETFL) | O_NONBLOCK); + ::fcntl(pipefd[1], F_SETFL, ::fcntl(pipefd[1], F_GETFL) | O_NONBLOCK); + } + + return 0; +} + +// don't call dup or fcntl(F_DUPFD) +static inline int qt_safe_dup(int oldfd, int atleast = 0, int flags = FD_CLOEXEC) +{ + Q_ASSERT(flags == FD_CLOEXEC || flags == 0); + + register int ret; +#ifdef F_DUPFD_CLOEXEC + // use this fcntl + if (flags & FD_CLOEXEC) { + ret = ::fcntl(oldfd, F_DUPFD_CLOEXEC, atleast); + if (ret != -1 || errno != EINVAL) + return ret; + } +#endif + + // use F_DUPFD + ret = ::fcntl(oldfd, F_DUPFD, atleast); + + if (flags && ret != -1) + ::fcntl(ret, F_SETFD, flags); + return ret; +} + +// don't call dup2 +// call qt_safe_dup2 +static inline int qt_safe_dup2(int oldfd, int newfd, int flags = FD_CLOEXEC) +{ + Q_ASSERT(flags == FD_CLOEXEC || flags == 0); + + register int ret; +#if QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC + // use dup3 + if (flags & FD_CLOEXEC) { + EINTR_LOOP(ret, ::dup3(oldfd, newfd, O_CLOEXEC)); + if (ret == 0 || errno != ENOSYS) + return ret; + } +#endif + EINTR_LOOP(ret, ::dup2(oldfd, newfd)); + if (ret == -1) + return -1; + + if (flags) + ::fcntl(newfd, F_SETFD, flags); + return 0; +} + +static inline qint64 qt_safe_read(int fd, char *data, qint64 maxlen) +{ + qint64 ret = 0; + EINTR_LOOP(ret, QT_READ(fd, data, maxlen)); + return ret; +} +#undef QT_READ +#define QT_READ qt_safe_read + +static inline qint64 qt_safe_write(int fd, const char *data, qint64 len) +{ + qint64 ret = 0; + EINTR_LOOP(ret, QT_WRITE(fd, data, len)); + return ret; +} +#undef QT_WRITE +#define QT_WRITE qt_safe_write + +static inline int qt_safe_close(int fd) +{ + register int ret; + EINTR_LOOP(ret, QT_CLOSE(fd)); + return ret; +} +#undef QT_CLOSE +#define QT_CLOSE qt_safe_close + +static inline int qt_safe_execve(const char *filename, char *const argv[], + char *const envp[]) +{ + register int ret; + EINTR_LOOP(ret, ::execve(filename, argv, envp)); + return ret; +} + +static inline int qt_safe_execv(const char *path, char *const argv[]) +{ + register int ret; + EINTR_LOOP(ret, ::execv(path, argv)); + return ret; +} + +static inline int qt_safe_execvp(const char *file, char *const argv[]) +{ + register int ret; + EINTR_LOOP(ret, ::execvp(file, argv)); + return ret; +} + +static inline pid_t qt_safe_waitpid(pid_t pid, int *status, int options) +{ + register int ret; + EINTR_LOOP(ret, ::waitpid(pid, status, options)); + return ret; +} + +Q_CORE_EXPORT int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept, + const struct timeval *tv); + +QT_END_NAMESPACE + +#endif -- cgit v0.12 From 29302d2429ed81f4396155383b602e7bde4edd3b Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 22 Apr 2009 17:30:51 +0200 Subject: Port most uses of ::open and QT_OPEN to the safe version. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This ensures that we're calling the open64 version of this function as well as handling the O_CLOEXEC flag and EINTR errors. Reviewed-By: João Abecasis --- src/corelib/io/qfilesystemwatcher_kqueue.cpp | 5 +++-- src/corelib/io/qfsfileengine_unix.cpp | 18 +++++++----------- src/corelib/io/qresource.cpp | 4 ++++ src/corelib/io/qtemporaryfile.cpp | 17 ++++++----------- src/corelib/kernel/qsharedmemory_unix.cpp | 4 +++- src/corelib/kernel/qtranslator.cpp | 1 + 6 files changed, 24 insertions(+), 25 deletions(-) diff --git a/src/corelib/io/qfilesystemwatcher_kqueue.cpp b/src/corelib/io/qfilesystemwatcher_kqueue.cpp index ed42c34..721f52c 100644 --- a/src/corelib/io/qfilesystemwatcher_kqueue.cpp +++ b/src/corelib/io/qfilesystemwatcher_kqueue.cpp @@ -43,6 +43,7 @@ #include "qfilesystemwatcher.h" #include "qfilesystemwatcher_kqueue_p.h" +#include "qcore_unix_p.h" #include #include @@ -124,9 +125,9 @@ QStringList QKqueueFileSystemWatcherEngine::addPaths(const QStringList &paths, QString path = it.next(); int fd; #if defined(O_EVTONLY) - fd = ::open(QFile::encodeName(path), O_EVTONLY); + fd = qt_safe_open(QFile::encodeName(path), O_EVTONLY); #else - fd = ::open(QFile::encodeName(path), O_RDONLY); + fd = qt_safe_open(QFile::encodeName(path), O_RDONLY); #endif if (fd == -1) { perror("QKqueueFileSystemWatcherEngine::addPaths: open"); diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index 4743a47..5708e9f 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -42,6 +42,7 @@ #include "qplatformdefs.h" #include "qabstractfileengine.h" #include "private/qfsfileengine_p.h" +#include "private/qcore_unix_p.h" #ifndef QT_NO_FSFILEENGINE @@ -90,6 +91,12 @@ static QByteArray openModeToFopenMode(QIODevice::OpenMode flags, const QString & if (flags & QIODevice::ReadOnly) mode += '+'; } + +#if defined(__GLIBC__) && (__GLIBC__ * 0x100 + __GLIBC_MINOR__) >= 0x0207 + // must be glibc >= 2.7 + mode += 'e'; +#endif + return mode; } @@ -118,12 +125,6 @@ static int openModeToOpenFlags(QIODevice::OpenMode mode) oflags |= QT_OPEN_TRUNC; } -#ifdef O_CLOEXEC - // supported on Linux >= 2.6.23; avoids one extra system call - // and avoids a race condition: if another thread forks, we could - // end up leaking a file descriptor... - oflags |= O_CLOEXEC; -#endif return oflags; } @@ -177,11 +178,6 @@ bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode) } } -#ifndef O_CLOEXEC - // not needed on Linux >= 2.6.23 - setCloseOnExec(fd); // ignore failure -#endif - // Seek to the end when in Append mode. if (flags & QFile::Append) { int ret; diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp index fe8764d..a70b92f 100644 --- a/src/corelib/io/qresource.cpp +++ b/src/corelib/io/qresource.cpp @@ -56,6 +56,10 @@ #include #include "private/qabstractfileengine_p.h" +#ifdef Q_OS_UNIX +# include "private/qcore_unix_p.h" +#endif + //#define DEBUG_RESOURCE_MATCH QT_BEGIN_NAMESPACE diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp index 62ab0c4..2ae4611 100644 --- a/src/corelib/io/qtemporaryfile.cpp +++ b/src/corelib/io/qtemporaryfile.cpp @@ -60,6 +60,10 @@ #include #include +#if defined(Q_OS_UNIX) +# include "private/qcore_unix_p.h" +#endif + #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) # include # if defined(_MSC_VER) && _MSC_VER >= 1400 @@ -72,7 +76,6 @@ # include "qfunctions_wince.h" #endif - QT_BEGIN_NAMESPACE /* @@ -208,8 +211,9 @@ static int _gettemp(char *path, int *doopen, int domkdir, int slen) if ((*doopen = QT_OPEN(targetPath.toLocal8Bit(), O_CREAT|O_EXCL|O_RDWR # else // CE + // this is Unix if ((*doopen = - open(path, QT_OPEN_CREAT|O_EXCL|QT_OPEN_RDWR + qt_safe_open(path, QT_OPEN_CREAT|O_EXCL|QT_OPEN_RDWR # endif # ifdef QT_LARGEFILE_SUPPORT |QT_OPEN_LARGEFILE @@ -219,18 +223,9 @@ static int _gettemp(char *path, int *doopen, int domkdir, int slen) # elif defined(Q_OS_WIN) |O_BINARY # endif -# ifdef O_CLOEXEC - // supported on Linux >= 2.6.23; avoids one extra system call - // and avoids a race condition: if another thread forks, we could - // end up leaking a file descriptor... - |O_CLOEXEC -# endif , 0600)) >= 0) #endif // WIN && !CE { -#if defined(Q_OS_UNIX) && !defined(O_CLOEXEC) - fcntl(*doopen, F_SETFD, FD_CLOEXEC); -#endif return 1; } if (errno != EEXIST) diff --git a/src/corelib/kernel/qsharedmemory_unix.cpp b/src/corelib/kernel/qsharedmemory_unix.cpp index 5299972..04739ff 100644 --- a/src/corelib/kernel/qsharedmemory_unix.cpp +++ b/src/corelib/kernel/qsharedmemory_unix.cpp @@ -59,6 +59,8 @@ #include #include +#include "private/qcore_unix_p.h" + QT_BEGIN_NAMESPACE QSharedMemoryPrivate::QSharedMemoryPrivate() @@ -153,7 +155,7 @@ int QSharedMemoryPrivate::createUnixKeyFile(const QString &fileName) if (QFile::exists(fileName)) return 0; - int fd = open(QFile::encodeName(fileName).constData(), + int fd = qt_safe_open(QFile::encodeName(fileName).constData(), O_EXCL | O_CREAT | O_RDWR, 0640); if (-1 == fd) { if (errno == EEXIST) diff --git a/src/corelib/kernel/qtranslator.cpp b/src/corelib/kernel/qtranslator.cpp index 64cf16e..4aed2b2 100644 --- a/src/corelib/kernel/qtranslator.cpp +++ b/src/corelib/kernel/qtranslator.cpp @@ -58,6 +58,7 @@ #if defined(Q_OS_UNIX) #define QT_USE_MMAP +#include "private/qcore_unix_p.h" #endif // most of the headers below are already included in qplatformdefs.h -- cgit v0.12 From 557258e8f944f0003e9b71e5fe11fcb458db71d8 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 22 Apr 2009 18:01:05 +0200 Subject: Make the inotify_init call also use FD_CLOEXEC-safe version of the system call Reviewed-By: ossi --- src/corelib/io/qfilesystemwatcher_inotify.cpp | 40 +++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/src/corelib/io/qfilesystemwatcher_inotify.cpp b/src/corelib/io/qfilesystemwatcher_inotify.cpp index 401e545..9d08228 100644 --- a/src/corelib/io/qfilesystemwatcher_inotify.cpp +++ b/src/corelib/io/qfilesystemwatcher_inotify.cpp @@ -44,6 +44,8 @@ #ifndef QT_NO_FILESYSTEMWATCHER +#include "private/qcore_unix_p.h" + #include #include #include @@ -62,62 +64,80 @@ # define __NR_inotify_init 291 # define __NR_inotify_add_watch 292 # define __NR_inotify_rm_watch 293 +# define __NR_inotify_init1 332 #elif defined(__x86_64__) # define __NR_inotify_init 253 # define __NR_inotify_add_watch 254 # define __NR_inotify_rm_watch 255 +# define __NR_inotify_init1 294 #elif defined(__powerpc__) || defined(__powerpc64__) # define __NR_inotify_init 275 # define __NR_inotify_add_watch 276 # define __NR_inotify_rm_watch 277 +# define __NR_inotify_init1 318 #elif defined (__ia64__) # define __NR_inotify_init 1277 # define __NR_inotify_add_watch 1278 # define __NR_inotify_rm_watch 1279 +# define __NR_inotify_init1 1318 #elif defined (__s390__) || defined (__s390x__) # define __NR_inotify_init 284 # define __NR_inotify_add_watch 285 # define __NR_inotify_rm_watch 286 +# define __NR_inotify_init1 324 #elif defined (__alpha__) # define __NR_inotify_init 444 # define __NR_inotify_add_watch 445 # define __NR_inotify_rm_watch 446 +// no inotify_init1 for the Alpha #elif defined (__sparc__) || defined (__sparc64__) # define __NR_inotify_init 151 # define __NR_inotify_add_watch 152 # define __NR_inotify_rm_watch 156 +# define __NR_inotify_init1 322 #elif defined (__arm__) # define __NR_inotify_init 316 # define __NR_inotify_add_watch 317 # define __NR_inotify_rm_watch 318 +# define __NR_inotify_init1 360 #elif defined (__sh__) # define __NR_inotify_init 290 # define __NR_inotify_add_watch 291 # define __NR_inotify_rm_watch 292 +# define __NR_inotify_init1 332 #elif defined (__sh64__) # define __NR_inotify_init 318 # define __NR_inotify_add_watch 319 # define __NR_inotify_rm_watch 320 +# define __NR_inotify_init1 360 #elif defined (__mips__) # define __NR_inotify_init 284 # define __NR_inotify_add_watch 285 # define __NR_inotify_rm_watch 286 +# define __NR_inotify_init1 329 #elif defined (__hppa__) # define __NR_inotify_init 269 # define __NR_inotify_add_watch 270 # define __NR_inotify_rm_watch 271 +# define __NR_inotify_init1 314 #elif defined (__avr32__) # define __NR_inotify_init 240 # define __NR_inotify_add_watch 241 # define __NR_inotify_rm_watch 242 +// no inotify_init1 for AVR32 #elif defined (__mc68000__) # define __NR_inotify_init 284 # define __NR_inotify_add_watch 285 # define __NR_inotify_rm_watch 286 +# define __NR_inotify_init1 328 #else # error "This architecture is not supported. Please talk to qt-bugs@trolltech.com" #endif +#if !defined(IN_CLOEXEC) && defined(O_CLOEXEC) && defined(__NR_inotify_init1) +# define IN_CLOEXEC O_CLOEXEC +#endif + QT_BEGIN_NAMESPACE #ifdef QT_LINUXBASE @@ -140,6 +160,13 @@ static inline int inotify_rm_watch(int fd, __u32 wd) return syscall(__NR_inotify_rm_watch, fd, wd); } +#ifdef IN_CLOEXEC +static inline int inotify_init1(int flags) +{ + return syscall(__NR_inotify_init1, flags); +} +#endif + // the following struct and values are documented in linux/inotify.h extern "C" { @@ -185,9 +212,16 @@ QT_BEGIN_NAMESPACE QInotifyFileSystemWatcherEngine *QInotifyFileSystemWatcherEngine::create() { - int fd = inotify_init(); - if (fd <= 0) - return 0; + register int fd = -1; +#ifdef IN_CLOEXEC + fd = inotify_init1(IN_CLOEXEC); +#endif + if (fd == -1) { + fd = inotify_init(); + if (fd == -1) + return 0; + ::fcntl(fd, F_SETFD, FD_CLOEXEC); + } return new QInotifyFileSystemWatcherEngine(fd); } -- cgit v0.12 From 1d965e189dfd5c9977565ca0c20224806aa7473d Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 22 Apr 2009 19:02:32 +0200 Subject: Use the safe versions in these system calls I've just introduced. Reviewed-By: ossi --- src/corelib/io/qfilesystemwatcher_dnotify.cpp | 20 ++++++++++---------- src/corelib/io/qfsfileengine.cpp | 3 +++ src/corelib/io/qfsfileengine_unix.cpp | 2 +- src/corelib/kernel/qeventdispatcher_unix.cpp | 12 +++++++----- src/gui/painting/qpdf.cpp | 20 ++++++++++++-------- 5 files changed, 33 insertions(+), 24 deletions(-) diff --git a/src/corelib/io/qfilesystemwatcher_dnotify.cpp b/src/corelib/io/qfilesystemwatcher_dnotify.cpp index c68af85..6df3746 100644 --- a/src/corelib/io/qfilesystemwatcher_dnotify.cpp +++ b/src/corelib/io/qfilesystemwatcher_dnotify.cpp @@ -59,6 +59,8 @@ #include #include +#include "private/qcore_unix_p.h" + #ifdef QT_LINUXBASE /* LSB doesn't standardize these */ @@ -80,7 +82,7 @@ static void (*qfswd_old_sigio_handler)(int) = 0; static void (*qfswd_old_sigio_action)(int, siginfo_t *, void *) = 0; static void qfswd_sigio_monitor(int signum, siginfo_t *i, void *v) { - ::write(qfswd_fileChanged_pipe[1], &i->si_fd, sizeof(int)); + qt_safe_write(qfswd_fileChanged_pipe[1], reinterpret_cast(&i->si_fd), sizeof(int)); if (qfswd_old_sigio_handler && qfswd_old_sigio_handler != SIG_IGN) qfswd_old_sigio_handler(signum); @@ -121,9 +123,7 @@ QDnotifySignalThread::QDnotifySignalThread() { moveToThread(this); - ::pipe(qfswd_fileChanged_pipe); - ::fcntl(qfswd_fileChanged_pipe[0], F_SETFL, - ::fcntl(qfswd_fileChanged_pipe[0], F_GETFL) | O_NONBLOCK); + qt_safe_pipe(qfswd_fileChanged_pipe, O_NONBLOCK); struct sigaction oldAction; struct sigaction action; @@ -181,7 +181,7 @@ void QDnotifySignalThread::run() void QDnotifySignalThread::readFromDnotify() { int fd; - int readrv = ::read(qfswd_fileChanged_pipe[0], &fd,sizeof(int)); + int readrv = qt_safe_read(qfswd_fileChanged_pipe[0], reinterpret_cast(&fd), sizeof(int)); // Only expect EAGAIN or EINTR. Other errors are assumed to be impossible. if(readrv != -1) { Q_ASSERT(readrv == sizeof(int)); @@ -207,9 +207,9 @@ QDnotifyFileSystemWatcherEngine::~QDnotifyFileSystemWatcherEngine() for(QHash::ConstIterator iter = fdToDirectory.constBegin(); iter != fdToDirectory.constEnd(); ++iter) { - ::close(iter->fd); + qt_safe_close(iter->fd); if(iter->parentFd) - ::close(iter->parentFd); + qt_safe_close(iter->parentFd); } } @@ -353,7 +353,7 @@ QStringList QDnotifyFileSystemWatcherEngine::removePaths(const QStringList &path if(!directory.isMonitored && directory.files.isEmpty()) { // No longer needed - ::close(directory.fd); + qt_safe_close(directory.fd); pathToFD.remove(directory.path); fdToDirectory.remove(fd); } @@ -419,9 +419,9 @@ void QDnotifyFileSystemWatcherEngine::refresh(int fd) } if(!directory.isMonitored && directory.files.isEmpty()) { - ::close(directory.fd); + qt_safe_close(directory.fd); if(directory.parentFd) { - ::close(directory.parentFd); + qt_safe_close(directory.parentFd); parentToFD.remove(directory.parentFd); } fdToDirectory.erase(iter); diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp index e32b818..beafe72 100644 --- a/src/corelib/io/qfsfileengine.cpp +++ b/src/corelib/io/qfsfileengine.cpp @@ -50,6 +50,9 @@ #if !defined(Q_OS_WINCE) #include #endif +#if defined(Q_OS_UNIX) +#include "private/qcore_unix_p.h" +#endif #include QT_BEGIN_NAMESPACE diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index 5708e9f..47e3db0 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -458,7 +458,7 @@ bool QFSFileEngine::caseSensitive() const bool QFSFileEngine::setCurrentPath(const QString &path) { int r; - r = ::chdir(QFile::encodeName(path)); + r = QT_CHDIR(QFile::encodeName(path)); return r >= 0; } diff --git a/src/corelib/kernel/qeventdispatcher_unix.cpp b/src/corelib/kernel/qeventdispatcher_unix.cpp index 161398e..0eeea04 100644 --- a/src/corelib/kernel/qeventdispatcher_unix.cpp +++ b/src/corelib/kernel/qeventdispatcher_unix.cpp @@ -49,6 +49,7 @@ #include "qeventdispatcher_unix_p.h" #include #include +#include #include #include @@ -76,6 +77,7 @@ static void signalHandler(int sig) } +#ifdef Q_OS_INTEGRITY static void initThreadPipeFD(int fd) { int ret = fcntl(fd, F_SETFD, FD_CLOEXEC); @@ -90,7 +92,7 @@ static void initThreadPipeFD(int fd) if (ret == -1) perror("QEventDispatcherUNIXPrivate: Unable to set flags on thread pipe"); } - +#endif QEventDispatcherUNIXPrivate::QEventDispatcherUNIXPrivate() { @@ -102,13 +104,13 @@ QEventDispatcherUNIXPrivate::QEventDispatcherUNIXPrivate() // INTEGRITY doesn't like a "select" on pipes, so use socketpair instead if (socketpair(AF_INET, SOCK_STREAM, PF_INET, thread_pipe) == -1) perror("QEventDispatcherUNIXPrivate(): Unable to create socket pair"); -#else - if (pipe(thread_pipe) == -1) - perror("QEventDispatcherUNIXPrivate(): Unable to create thread pipe"); -#endif initThreadPipeFD(thread_pipe[0]); initThreadPipeFD(thread_pipe[1]); +#else + if (qt_safe_pipe(thread_pipe, O_NONBLOCK) == -1) + perror("QEventDispatcherUNIXPrivate(): Unable to create thread pipe"); +#endif sn_highest = -1; diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp index a6ecd4e..178d519 100644 --- a/src/gui/painting/qpdf.cpp +++ b/src/gui/painting/qpdf.cpp @@ -48,6 +48,10 @@ #include "qprinterinfo.h" #include +#ifdef Q_OS_UNIX +#include "private/qcore_unix_p.h" // overrides QT_OPEN +#endif + QT_BEGIN_NAMESPACE extern int qt_defaultDpi(); @@ -1647,7 +1651,7 @@ static void closeAllOpenFds() #endif // leave stdin/out/err untouched while(--i > 2) - ::close(i); + QT_CLOSE(i); } #endif @@ -1681,7 +1685,7 @@ bool QPdfBaseEnginePrivate::openPrintDevice() if (!printerName.isEmpty()) pr = printerName; int fds[2]; - if (pipe(fds) != 0) { + if (qt_safe_pipe(fds) != 0) { qWarning("QPdfPrinter: Could not open pipe to print"); return false; } @@ -1700,9 +1704,9 @@ bool QPdfBaseEnginePrivate::openPrintDevice() (void)execlp("true", "true", (char *)0); (void)execl("/bin/true", "true", (char *)0); (void)execl("/usr/bin/true", "true", (char *)0); - ::exit(0); + ::_exit(0); } - dup2(fds[0], 0); + qt_safe_dup2(fds[0], 0, 0); closeAllOpenFds(); @@ -1769,14 +1773,14 @@ bool QPdfBaseEnginePrivate::openPrintDevice() // wait for a second so the parent process (the // child of the GUI process) has exited. then // exit. - ::close(0); + QT_CLOSE(0); (void)::sleep(1); - ::exit(0); + ::_exit(0); } // parent process - ::close(fds[0]); + QT_CLOSE(fds[0]); fd = fds[1]; - (void)::waitpid(pid, 0, 0); + (void)qt_safe_waitpid(pid, 0, 0); if (fd < 0) return false; -- cgit v0.12 From de05f9a40e41deb79daf5c4935b2645d70d7f322 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 22 Apr 2009 19:04:32 +0200 Subject: Port QProcess to use the EINTR-safe and thread-safe functions Reviewed-By: ossi --- src/corelib/io/qprocess_unix.cpp | 213 ++++++++++++--------------------------- 1 file changed, 65 insertions(+), 148 deletions(-) diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp index 49869a4..c81da44 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -84,6 +84,7 @@ QT_END_NAMESPACE #include "qprocess.h" #include "qprocess_p.h" +#include "private/qcore_unix_p.h" #ifdef Q_OS_MAC #include @@ -114,78 +115,11 @@ static inline char *strdup(const char *data) } #endif -static qint64 qt_native_read(int fd, char *data, qint64 maxlen) -{ - qint64 ret = 0; - do { - ret = ::read(fd, data, maxlen); - } while (ret == -1 && errno == EINTR); - return ret; -} - -static qint64 qt_native_write(int fd, const char *data, qint64 len) -{ - qint64 ret = 0; - do { - ret = ::write(fd, data, len); - } while (ret == -1 && errno == EINTR); - return ret; -} - -static void qt_native_close(int fd) -{ - int ret; - do { - ret = ::close(fd); - } while (ret == -1 && errno == EINTR); -} - -static void qt_native_dup2(int oldfd, int newfd) -{ - int ret; - do { - ret = ::dup2(oldfd, newfd); - } while (ret == -1 && errno == EINTR); -} - -static void qt_native_chdir(const char *path) -{ - int ret; - do { - ret = ::chdir(path); - } while (ret == -1 && errno == EINTR); -} - -static void qt_native_execve(const char *filename, char *const argv[], - char *const envp[]) -{ - int ret; - do { - ret = ::execve(filename, argv, envp); - } while (ret == -1 && errno == EINTR); -} - -static void qt_native_execv(const char *path, char *const argv[]) -{ - int ret; - do { - ret = ::execv(path, argv); - } while (ret == -1 && errno == EINTR); -} - -static void qt_native_execvp(const char *file, char *const argv[]) -{ - int ret; - do { - ret = ::execvp(file, argv); - } while (ret == -1 && errno == EINTR); -} - static int qt_qprocess_deadChild_pipe[2]; static void (*qt_sa_old_sigchld_handler)(int) = 0; static void qt_sa_sigchld_handler(int signum) { - qt_native_write(qt_qprocess_deadChild_pipe[1], "", 1); + qt_safe_write(qt_qprocess_deadChild_pipe[1], "", 1); #if defined (QPROCESS_DEBUG) fprintf(stderr, "*** SIGCHLD\n"); #endif @@ -231,13 +165,7 @@ QProcessManager::QProcessManager() // initialize the dead child pipe and make it non-blocking. in the // extremely unlikely event that the pipe fills up, we do not under any // circumstances want to block. - ::pipe(qt_qprocess_deadChild_pipe); - ::fcntl(qt_qprocess_deadChild_pipe[0], F_SETFD, FD_CLOEXEC); - ::fcntl(qt_qprocess_deadChild_pipe[1], F_SETFD, FD_CLOEXEC); - ::fcntl(qt_qprocess_deadChild_pipe[0], F_SETFL, - ::fcntl(qt_qprocess_deadChild_pipe[0], F_GETFL) | O_NONBLOCK); - ::fcntl(qt_qprocess_deadChild_pipe[1], F_SETFL, - ::fcntl(qt_qprocess_deadChild_pipe[1], F_GETFL) | O_NONBLOCK); + qt_safe_pipe(qt_qprocess_deadChild_pipe, O_NONBLOCK); // set up the SIGCHLD handler, which writes a single byte to the dead // child pipe every time a child dies. @@ -254,13 +182,13 @@ QProcessManager::QProcessManager() QProcessManager::~QProcessManager() { // notify the thread that we're shutting down. - qt_native_write(qt_qprocess_deadChild_pipe[1], "@", 1); - qt_native_close(qt_qprocess_deadChild_pipe[1]); + qt_safe_write(qt_qprocess_deadChild_pipe[1], "@", 1); + qt_safe_close(qt_qprocess_deadChild_pipe[1]); wait(); // on certain unixes, closing the reading end of the pipe will cause // select in run() to block forever, rather than return with EBADF. - qt_native_close(qt_qprocess_deadChild_pipe[0]); + qt_safe_close(qt_qprocess_deadChild_pipe[0]); qt_qprocess_deadChild_pipe[0] = -1; qt_qprocess_deadChild_pipe[1] = -1; @@ -304,7 +232,7 @@ void QProcessManager::run() // signals may have been delivered in the meantime, to avoid race // conditions. char c; - if (qt_native_read(qt_qprocess_deadChild_pipe[0], &c, 1) < 0 || c == '@') + if (qt_safe_read(qt_qprocess_deadChild_pipe[0], &c, 1) < 0 || c == '@') break; // catch any and all children that we can. @@ -323,7 +251,7 @@ void QProcessManager::catchDeadChildren() // notify all children that they may have died. they need to run // waitpid() in their own thread. QProcessInfo *info = it.value(); - qt_native_write(info->deathPipe, "", 1); + qt_safe_write(info->deathPipe, "", 1); #if defined (QPROCESS_DEBUG) qDebug() << "QProcessManager::run() sending death notice to" << info->process; @@ -382,25 +310,23 @@ void QProcessManager::unlock() static void qt_create_pipe(int *pipe) { if (pipe[0] != -1) - qt_native_close(pipe[0]); + qt_safe_close(pipe[0]); if (pipe[1] != -1) - qt_native_close(pipe[1]); - if (::pipe(pipe) != 0) { + qt_safe_close(pipe[1]); + if (qt_safe_pipe(pipe) != 0) { qWarning("QProcessPrivate::createPipe: Cannot create pipe %p: %s", pipe, qPrintable(qt_error_string(errno))); } - ::fcntl(pipe[0], F_SETFD, FD_CLOEXEC); - ::fcntl(pipe[1], F_SETFD, FD_CLOEXEC); } void QProcessPrivate::destroyPipe(int *pipe) { if (pipe[1] != -1) { - qt_native_close(pipe[1]); + qt_safe_close(pipe[1]); pipe[1] = -1; } if (pipe[0] != -1) { - qt_native_close(pipe[0]); + qt_safe_close(pipe[0]); pipe[0] = -1; } } @@ -453,7 +379,7 @@ bool QProcessPrivate::createChannel(Channel &channel) if (&channel == &stdinChannel) { // try to open in read-only mode channel.pipe[1] = -1; - if ( (channel.pipe[0] = QT_OPEN(fname, O_RDONLY)) != -1) + if ( (channel.pipe[0] = qt_safe_open(fname, O_RDONLY)) != -1) return true; // success q->setErrorString(QProcess::tr("Could not open input redirection for reading")); @@ -465,7 +391,7 @@ bool QProcessPrivate::createChannel(Channel &channel) mode |= O_TRUNC; channel.pipe[0] = -1; - if ( (channel.pipe[1] = QT_OPEN(fname, mode, 0666)) != -1) + if ( (channel.pipe[1] = qt_safe_open(fname, mode, 0666)) != -1) return true; // success q->setErrorString(QProcess::tr("Could not open output redirection for writing")); @@ -586,8 +512,6 @@ void QProcessPrivate::startProcess() return; qt_create_pipe(childStartedPipe); qt_create_pipe(deathPipe); - ::fcntl(deathPipe[0], F_SETFD, FD_CLOEXEC); - ::fcntl(deathPipe[1], F_SETFD, FD_CLOEXEC); if (threadData->eventDispatcher) { startupSocketNotifier = new QSocketNotifier(childStartedPipe[0], @@ -728,11 +652,11 @@ void QProcessPrivate::startProcess() // parent // close the ends we don't use and make all pipes non-blocking ::fcntl(deathPipe[0], F_SETFL, ::fcntl(deathPipe[0], F_GETFL) | O_NONBLOCK); - qt_native_close(childStartedPipe[1]); + qt_safe_close(childStartedPipe[1]); childStartedPipe[1] = -1; if (stdinChannel.pipe[0] != -1) { - qt_native_close(stdinChannel.pipe[0]); + qt_safe_close(stdinChannel.pipe[0]); stdinChannel.pipe[0] = -1; } @@ -740,7 +664,7 @@ void QProcessPrivate::startProcess() ::fcntl(stdinChannel.pipe[1], F_SETFL, ::fcntl(stdinChannel.pipe[1], F_GETFL) | O_NONBLOCK); if (stdoutChannel.pipe[1] != -1) { - qt_native_close(stdoutChannel.pipe[1]); + qt_safe_close(stdoutChannel.pipe[1]); stdoutChannel.pipe[1] = -1; } @@ -748,7 +672,7 @@ void QProcessPrivate::startProcess() ::fcntl(stdoutChannel.pipe[0], F_SETFL, ::fcntl(stdoutChannel.pipe[0], F_GETFL) | O_NONBLOCK); if (stderrChannel.pipe[1] != -1) { - qt_native_close(stderrChannel.pipe[1]); + qt_safe_close(stderrChannel.pipe[1]); stderrChannel.pipe[1] = -1; } if (stderrChannel.pipe[0] != -1) @@ -761,35 +685,34 @@ void QProcessPrivate::execChild(const char *workingDir, char **path, char **argv Q_Q(QProcess); - // copy the stdin socket - qt_native_dup2(stdinChannel.pipe[0], fileno(stdin)); + // copy the stdin socket (without closing on exec) + qt_safe_dup2(stdinChannel.pipe[0], fileno(stdin), 0); // copy the stdout and stderr if asked to if (processChannelMode != QProcess::ForwardedChannels) { - qt_native_dup2(stdoutChannel.pipe[1], fileno(stdout)); + qt_safe_dup2(stdoutChannel.pipe[1], fileno(stdout), 0); // merge stdout and stderr if asked to if (processChannelMode == QProcess::MergedChannels) { - qt_native_dup2(fileno(stdout), fileno(stderr)); + qt_safe_dup2(fileno(stdout), fileno(stderr), 0); } else { - qt_native_dup2(stderrChannel.pipe[1], fileno(stderr)); + qt_safe_dup2(stderrChannel.pipe[1], fileno(stderr), 0); } } // make sure this fd is closed if execvp() succeeds - qt_native_close(childStartedPipe[0]); - ::fcntl(childStartedPipe[1], F_SETFD, FD_CLOEXEC); + qt_safe_close(childStartedPipe[0]); // enter the working directory if (workingDir) - qt_native_chdir(workingDir); + QT_CHDIR(workingDir); // this is a virtual call, and it base behavior is to do nothing. q->setupChildProcess(); // execute the process if (!envp) { - qt_native_execvp(argv[0], argv); + qt_safe_execvp(argv[0], argv); } else { if (path) { char **arg = path; @@ -798,14 +721,14 @@ void QProcessPrivate::execChild(const char *workingDir, char **path, char **argv #if defined (QPROCESS_DEBUG) fprintf(stderr, "QProcessPrivate::execChild() searching / starting %s\n", argv[0]); #endif - qt_native_execve(argv[0], argv, envp); + qt_safe_execve(argv[0], argv, envp); ++arg; } } else { #if defined (QPROCESS_DEBUG) fprintf(stderr, "QProcessPrivate::execChild() starting %s\n", argv[0]); #endif - qt_native_execve(argv[0], argv, envp); + qt_safe_execve(argv[0], argv, envp); } } @@ -813,21 +736,21 @@ void QProcessPrivate::execChild(const char *workingDir, char **path, char **argv #if defined (QPROCESS_DEBUG) fprintf(stderr, "QProcessPrivate::execChild() failed, notifying parent process\n"); #endif - qt_native_write(childStartedPipe[1], "", 1); - qt_native_close(childStartedPipe[1]); + qt_safe_write(childStartedPipe[1], "", 1); + qt_safe_close(childStartedPipe[1]); childStartedPipe[1] = -1; } bool QProcessPrivate::processStarted() { char c; - int i = qt_native_read(childStartedPipe[0], &c, 1); + int i = qt_safe_read(childStartedPipe[0], &c, 1); if (startupSocketNotifier) { startupSocketNotifier->setEnabled(false); startupSocketNotifier->deleteLater(); startupSocketNotifier = 0; } - qt_native_close(childStartedPipe[0]); + qt_safe_close(childStartedPipe[0]); childStartedPipe[0] = -1; #if defined (QPROCESS_DEBUG) @@ -862,7 +785,7 @@ qint64 QProcessPrivate::bytesAvailableFromStderr() const qint64 QProcessPrivate::readFromStdout(char *data, qint64 maxlen) { - qint64 bytesRead = qt_native_read(stdoutChannel.pipe[0], data, maxlen); + qint64 bytesRead = qt_safe_read(stdoutChannel.pipe[0], data, maxlen); #if defined QPROCESS_DEBUG qDebug("QProcessPrivate::readFromStdout(%p \"%s\", %lld) == %lld", data, qt_prettyDebug(data, bytesRead, 16).constData(), maxlen, bytesRead); @@ -872,7 +795,7 @@ qint64 QProcessPrivate::readFromStdout(char *data, qint64 maxlen) qint64 QProcessPrivate::readFromStderr(char *data, qint64 maxlen) { - qint64 bytesRead = qt_native_read(stderrChannel.pipe[0], data, maxlen); + qint64 bytesRead = qt_safe_read(stderrChannel.pipe[0], data, maxlen); #if defined QPROCESS_DEBUG qDebug("QProcessPrivate::readFromStderr(%p \"%s\", %lld) == %lld", data, qt_prettyDebug(data, bytesRead, 16).constData(), maxlen, bytesRead); @@ -896,7 +819,7 @@ qint64 QProcessPrivate::writeToStdin(const char *data, qint64 maxlen) { qt_ignore_sigpipe(); - qint64 written = qt_native_write(stdinChannel.pipe[1], data, maxlen); + qint64 written = qt_safe_write(stdinChannel.pipe[1], data, maxlen); #if defined QPROCESS_DEBUG qDebug("QProcessPrivate::writeToStdin(%p \"%s\", %lld) == %lld", data, qt_prettyDebug(data, maxlen, 16).constData(), maxlen, written); @@ -922,7 +845,7 @@ void QProcessPrivate::killProcess() ::kill(pid_t(pid), SIGKILL); } -static int qt_native_select(fd_set *fdread, fd_set *fdwrite, int timeout) +static int qt_safe_select(fd_set *fdread, fd_set *fdwrite, int timeout) { struct timeval tv; tv.tv_sec = timeout / 1000; @@ -962,7 +885,7 @@ bool QProcessPrivate::waitForStarted(int msecs) FD_SET(childStartedPipe[0], &fds); int ret; do { - ret = qt_native_select(&fds, 0, msecs); + ret = qt_safe_select(&fds, 0, msecs); } while (ret < 0 && errno == EINTR); if (ret == 0) { processError = QProcess::Timedout; @@ -1011,7 +934,7 @@ bool QProcessPrivate::waitForReadyRead(int msecs) FD_SET(stdinChannel.pipe[1], &fdwrite); int timeout = qt_timeout_value(msecs, stopWatch.elapsed()); - int ret = qt_native_select(&fdread, &fdwrite, timeout); + int ret = qt_safe_select(&fdread, &fdwrite, timeout); if (ret < 0) { if (errno == EINTR) continue; @@ -1084,7 +1007,7 @@ bool QProcessPrivate::waitForBytesWritten(int msecs) FD_SET(stdinChannel.pipe[1], &fdwrite); int timeout = qt_timeout_value(msecs, stopWatch.elapsed()); - int ret = qt_native_select(&fdread, &fdwrite, timeout); + int ret = qt_safe_select(&fdread, &fdwrite, timeout); if (ret < 0) { if (errno == EINTR) continue; @@ -1152,7 +1075,7 @@ bool QProcessPrivate::waitForFinished(int msecs) FD_SET(stdinChannel.pipe[1], &fdwrite); int timeout = qt_timeout_value(msecs, stopWatch.elapsed()); - int ret = qt_native_select(&fdread, &fdwrite, timeout); + int ret = qt_safe_select(&fdread, &fdwrite, timeout); if (ret < 0) { if (errno == EINTR) continue; @@ -1193,7 +1116,7 @@ bool QProcessPrivate::waitForWrite(int msecs) int ret; do { - ret = qt_native_select(0, &fdwrite, msecs < 0 ? 0 : msecs) == 1; + ret = qt_safe_select(0, &fdwrite, msecs < 0 ? 0 : msecs) == 1; } while (ret < 0 && errno == EINTR); return ret == 1; } @@ -1210,15 +1133,11 @@ bool QProcessPrivate::waitForDeadChild() // read a byte from the death pipe char c; - qt_native_read(deathPipe[0], &c, 1); + qt_safe_read(deathPipe[0], &c, 1); // check if our process is dead int exitStatus; - pid_t waitResult = 0; - do { - waitResult = waitpid(pid_t(pid), &exitStatus, WNOHANG); - } while ((waitResult == -1 && errno == EINTR)); - if (waitResult > 0) { + if (qt_safe_waitpid(pid_t(pid), &exitStatus, WNOHANG) > 0) { processManager()->remove(q); crashed = !WIFEXITED(exitStatus); exitCode = WEXITSTATUS(exitStatus); @@ -1262,16 +1181,15 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a ::setsid(); - qt_native_close(startedPipe[0]); - qt_native_close(pidPipe[0]); + qt_safe_close(startedPipe[0]); + qt_safe_close(pidPipe[0]); pid_t doubleForkPid = qt_fork(); if (doubleForkPid == 0) { - ::fcntl(startedPipe[1], F_SETFD, FD_CLOEXEC); - qt_native_close(pidPipe[1]); + qt_safe_close(pidPipe[1]); if (!encodedWorkingDirectory.isEmpty()) - qt_native_chdir(encodedWorkingDirectory.constData()); + QT_CHDIR(encodedWorkingDirectory.constData()); char **argv = new char *[arguments.size() + 2]; for (int i = 0; i < arguments.size(); ++i) { @@ -1292,13 +1210,13 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a if (!tmp.endsWith('/')) tmp += '/'; tmp += QFile::encodeName(program); argv[0] = tmp.data(); - qt_native_execv(argv[0], argv); + qt_safe_execv(argv[0], argv); } } } else { QByteArray tmp = QFile::encodeName(program); argv[0] = tmp.data(); - qt_native_execv(argv[0], argv); + qt_safe_execv(argv[0], argv); } struct sigaction noaction; @@ -1308,8 +1226,8 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a // '\1' means execv failed char c = '\1'; - qt_native_write(startedPipe[1], &c, 1); - qt_native_close(startedPipe[1]); + qt_safe_write(startedPipe[1], &c, 1); + qt_safe_close(startedPipe[1]); ::_exit(1); } else if (doubleForkPid == -1) { struct sigaction noaction; @@ -1319,40 +1237,39 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a // '\2' means internal error char c = '\2'; - qt_native_write(startedPipe[1], &c, 1); + qt_safe_write(startedPipe[1], &c, 1); } - qt_native_close(startedPipe[1]); - qt_native_write(pidPipe[1], (const char *)&doubleForkPid, sizeof(pid_t)); - qt_native_chdir("/"); + qt_safe_close(startedPipe[1]); + qt_safe_write(pidPipe[1], (const char *)&doubleForkPid, sizeof(pid_t)); + QT_CHDIR("/"); ::_exit(1); } - qt_native_close(startedPipe[1]); - qt_native_close(pidPipe[1]); + qt_safe_close(startedPipe[1]); + qt_safe_close(pidPipe[1]); if (childPid == -1) { - qt_native_close(startedPipe[0]); - qt_native_close(pidPipe[0]); + qt_safe_close(startedPipe[0]); + qt_safe_close(pidPipe[0]); return false; } char reply = '\0'; - int startResult = qt_native_read(startedPipe[0], &reply, 1); + int startResult = qt_safe_read(startedPipe[0], &reply, 1); int result; - qt_native_close(startedPipe[0]); - while (::waitpid(childPid, &result, 0) == -1 && errno == EINTR) - { } + qt_safe_close(startedPipe[0]); + qt_safe_waitpid(childPid, &result, 0); bool success = (startResult != -1 && reply == '\0'); if (success && pid) { pid_t actualPid = 0; - if (qt_native_read(pidPipe[0], (char *)&actualPid, sizeof(pid_t)) == sizeof(pid_t)) { + if (qt_safe_read(pidPipe[0], (char *)&actualPid, sizeof(pid_t)) == sizeof(pid_t)) { *pid = actualPid; } else { *pid = 0; } } - qt_native_close(pidPipe[0]); + qt_safe_close(pidPipe[0]); return success; } -- cgit v0.12 From 27fc6ef5dfb7d58af778de162298fdc4da34459f Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 22 Apr 2009 20:54:17 +0200 Subject: Add a properly-safe version of select(2). Do the timeout handling the right and cross-platform way. The code that was in QProcess worked only on Linux, where the kernel sets the remainder in the returned timeval structure. Reviewed-By: ossi --- src/corelib/io/qprocess_unix.cpp | 80 ++++++++-------- src/corelib/kernel/kernel.pri | 1 + src/corelib/kernel/qcore_unix.cpp | 121 ++++++++++++++++++++++++ src/network/socket/qnativesocketengine_unix.cpp | 53 ++--------- 4 files changed, 165 insertions(+), 90 deletions(-) create mode 100644 src/corelib/kernel/qcore_unix.cpp diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp index c81da44..fafce07 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -128,6 +128,13 @@ static void qt_sa_sigchld_handler(int signum) qt_sa_old_sigchld_handler(signum); } +static inline void add_fd(int &nfds, int fd, fd_set *fdset) +{ + FD_SET(fd, fdset); + if ((fd) > nfds) + nfds = fd; +} + struct QProcessInfo { QProcess *process; int deathPipe; @@ -845,17 +852,15 @@ void QProcessPrivate::killProcess() ::kill(pid_t(pid), SIGKILL); } -static int qt_safe_select(fd_set *fdread, fd_set *fdwrite, int timeout) +static int select_msecs(int nfds, fd_set *fdread, fd_set *fdwrite, int timeout) { + if (timeout < 0) + return qt_safe_select(nfds, fdread, fdwrite, 0, 0); + struct timeval tv; tv.tv_sec = timeout / 1000; tv.tv_usec = (timeout % 1000) * 1000; - - int ret; - do { - ret = select(FD_SETSIZE, fdread, fdwrite, 0, timeout < 0 ? 0 : &tv); - } while (ret < 0 && (errno == EINTR)); - return ret; + return qt_safe_select(nfds, fdread, fdwrite, 0, &tv); } /* @@ -883,11 +888,7 @@ bool QProcessPrivate::waitForStarted(int msecs) fd_set fds; FD_ZERO(&fds); FD_SET(childStartedPipe[0], &fds); - int ret; - do { - ret = qt_safe_select(&fds, 0, msecs); - } while (ret < 0 && errno == EINTR); - if (ret == 0) { + if (select_msecs(childStartedPipe[0] + 1, &fds, 0, msecs) == 0) { processError = QProcess::Timedout; q->setErrorString(QProcess::tr("Process operation timed out")); #if defined (QPROCESS_DEBUG) @@ -920,24 +921,23 @@ bool QProcessPrivate::waitForReadyRead(int msecs) FD_ZERO(&fdread); FD_ZERO(&fdwrite); + int nfds = deathPipe[0]; + FD_SET(deathPipe[0], &fdread); + if (processState == QProcess::Starting) - FD_SET(childStartedPipe[0], &fdread); + add_fd(nfds, childStartedPipe[0], &fdread); if (stdoutChannel.pipe[0] != -1) - FD_SET(stdoutChannel.pipe[0], &fdread); + add_fd(nfds, stdoutChannel.pipe[0], &fdread); if (stderrChannel.pipe[0] != -1) - FD_SET(stderrChannel.pipe[0], &fdread); - - FD_SET(deathPipe[0], &fdread); + add_fd(nfds, stderrChannel.pipe[0], &fdread); if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1) - FD_SET(stdinChannel.pipe[1], &fdwrite); + add_fd(nfds, stdinChannel.pipe[1], &fdwrite); int timeout = qt_timeout_value(msecs, stopWatch.elapsed()); - int ret = qt_safe_select(&fdread, &fdwrite, timeout); + int ret = select_msecs(nfds + 1, &fdread, &fdwrite, timeout); if (ret < 0) { - if (errno == EINTR) - continue; break; } if (ret == 0) { @@ -993,24 +993,24 @@ bool QProcessPrivate::waitForBytesWritten(int msecs) FD_ZERO(&fdread); FD_ZERO(&fdwrite); + int nfds = deathPipe[0]; + FD_SET(deathPipe[0], &fdread); + if (processState == QProcess::Starting) - FD_SET(childStartedPipe[0], &fdread); + add_fd(nfds, childStartedPipe[0], &fdread); if (stdoutChannel.pipe[0] != -1) - FD_SET(stdoutChannel.pipe[0], &fdread); + add_fd(nfds, stdoutChannel.pipe[0], &fdread); if (stderrChannel.pipe[0] != -1) - FD_SET(stderrChannel.pipe[0], &fdread); + add_fd(nfds, stderrChannel.pipe[0], &fdread); - FD_SET(deathPipe[0], &fdread); if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1) - FD_SET(stdinChannel.pipe[1], &fdwrite); + add_fd(nfds, stdinChannel.pipe[1], &fdwrite); int timeout = qt_timeout_value(msecs, stopWatch.elapsed()); - int ret = qt_safe_select(&fdread, &fdwrite, timeout); + int ret = select_msecs(nfds + 1, &fdread, &fdwrite, timeout); if (ret < 0) { - if (errno == EINTR) - continue; break; } @@ -1056,29 +1056,28 @@ bool QProcessPrivate::waitForFinished(int msecs) forever { fd_set fdread; fd_set fdwrite; + int nfds = -1; FD_ZERO(&fdread); FD_ZERO(&fdwrite); if (processState == QProcess::Starting) - FD_SET(childStartedPipe[0], &fdread); + add_fd(nfds, childStartedPipe[0], &fdread); if (stdoutChannel.pipe[0] != -1) - FD_SET(stdoutChannel.pipe[0], &fdread); + add_fd(nfds, stdoutChannel.pipe[0], &fdread); if (stderrChannel.pipe[0] != -1) - FD_SET(stderrChannel.pipe[0], &fdread); + add_fd(nfds, stderrChannel.pipe[0], &fdread); if (processState == QProcess::Running) - FD_SET(deathPipe[0], &fdread); + add_fd(nfds, deathPipe[0], &fdread); if (!writeBuffer.isEmpty() && stdinChannel.pipe[1] != -1) - FD_SET(stdinChannel.pipe[1], &fdwrite); + add_fd(nfds, stdinChannel.pipe[1], &fdwrite); int timeout = qt_timeout_value(msecs, stopWatch.elapsed()); - int ret = qt_safe_select(&fdread, &fdwrite, timeout); + int ret = select_msecs(nfds + 1, &fdread, &fdwrite, timeout); if (ret < 0) { - if (errno == EINTR) - continue; break; } if (ret == 0) { @@ -1113,12 +1112,7 @@ bool QProcessPrivate::waitForWrite(int msecs) fd_set fdwrite; FD_ZERO(&fdwrite); FD_SET(stdinChannel.pipe[1], &fdwrite); - - int ret; - do { - ret = qt_safe_select(0, &fdwrite, msecs < 0 ? 0 : msecs) == 1; - } while (ret < 0 && errno == EINTR); - return ret == 1; + return select_msecs(stdinChannel.pipe[1] + 1, 0, &fdwrite, msecs < 0 ? 0 : msecs) == 1; } void QProcessPrivate::findExitCode() diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri index 6f28029..8759578 100644 --- a/src/corelib/kernel/kernel.pri +++ b/src/corelib/kernel/kernel.pri @@ -88,6 +88,7 @@ mac { unix { SOURCES += \ + kernel/qcore_unix.cpp \ kernel/qcrashhandler.cpp \ kernel/qsharedmemory_unix.cpp \ kernel/qsystemsemaphore_unix.cpp diff --git a/src/corelib/kernel/qcore_unix.cpp b/src/corelib/kernel/qcore_unix.cpp new file mode 100644 index 0000000..ffaf958 --- /dev/null +++ b/src/corelib/kernel/qcore_unix.cpp @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qcore_unix_p.h" + +#include +#include +#include + +#include "qeventdispatcher_unix_p.h" // for the timeval operators + +#if !defined(QT_NO_CLOCK_MONOTONIC) +# if defined(QT_BOOTSTRAPPED) +# define QT_NO_CLOCK_MONOTONIC +# endif +#endif + +QT_BEGIN_NAMESPACE + +static inline timeval gettime() +{ + timeval tv; +#ifndef QT_NO_CLOCK_MONOTONIC + // use the monotonic clock + static volatile bool monotonicClockDisabled = false; + struct timespec ts; + if (!monotonicClockDisabled) { + if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) { + monotonicClockDisabled = true; + } else { + tv.tv_sec = ts.tv_sec; + tv.tv_usec = ts.tv_nsec / 1000; + return tv; + } + } +#endif + // use gettimeofday + ::gettimeofday(&tv, 0); + return tv; +} + +static inline bool time_update(struct timeval *tv, const struct timeval &start, + const struct timeval &timeout) +{ + struct timeval now = gettime(); + if (now < start) { + // clock reset, give up + return false; + } + + *tv = timeout + start - now; + return true; +} + +int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept, + const struct timeval *orig_timeout) +{ + if (!orig_timeout) { + // no timeout -> block forever + register int ret; + EINTR_LOOP(ret, select(nfds, fdread, fdwrite, fdexcept, 0)); + return ret; + } + + timeval start = gettime(); + timeval timeout = *orig_timeout; + + // loop and recalculate the timeout as needed + int ret; + forever { + ret = ::select(nfds, fdread, fdwrite, fdexcept, &timeout); + if (ret != -1 || errno != EINTR) + return ret; + + // recalculate the timeout + if (!time_update(&timeout, start, *orig_timeout)) { + // clock reset, fake timeout error + return 0; + } + } +} + +QT_END_NAMESPACE diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp index b130a9b..6eafe05 100644 --- a/src/network/socket/qnativesocketengine_unix.cpp +++ b/src/network/socket/qnativesocketengine_unix.cpp @@ -42,6 +42,7 @@ //#define QNATIVESOCKETENGINE_DEBUG #include "qnativesocketengine_p.h" +#include "private/qcore_unix_p.h" #include "qiodevice.h" #include "qhostaddress.h" #include "qvarlengtharray.h" @@ -833,33 +834,11 @@ int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool selectForRead) co tv.tv_sec = timeout / 1000; tv.tv_usec = (timeout % 1000) * 1000; - QTime timer; - timer.start(); - int retval; - do { - if (selectForRead) - retval = select(socketDescriptor + 1, &fds, 0, 0, timeout < 0 ? 0 : &tv); - else - retval = select(socketDescriptor + 1, 0, &fds, 0, timeout < 0 ? 0 : &tv); - - if (retval != -1 || errno != EINTR) - break; - - if (timeout > 0) { - // recalculate the timeout - int t = timeout - timer.elapsed(); - if (t < 0) { - // oops, timeout turned negative? - retval = -1; - break; - } - - tv.tv_sec = t / 1000; - tv.tv_usec = (t % 1000) * 1000; - } - } while (true); - + if (selectForRead) + retval = qt_safe_select(socketDescriptor + 1, &fds, 0, 0, timeout < 0 ? 0 : &tv); + else + retval = qt_safe_select(socketDescriptor + 1, 0, &fds, 0, timeout < 0 ? 0 : &tv); return retval; } @@ -880,28 +859,8 @@ int QNativeSocketEnginePrivate::nativeSelect(int timeout, bool checkRead, bool c tv.tv_sec = timeout / 1000; tv.tv_usec = (timeout % 1000) * 1000; - QTime timer; - timer.start(); - int ret; - do { - ret = select(socketDescriptor + 1, &fdread, &fdwrite, 0, timeout < 0 ? 0 : &tv); - if (ret != -1 || errno != EINTR) - break; - - if (timeout > 0) { - // recalculate the timeout - int t = timeout - timer.elapsed(); - if (t < 0) { - // oops, timeout turned negative? - ret = -1; - break; - } - - tv.tv_sec = t / 1000; - tv.tv_usec = (t % 1000) * 1000; - } - } while (true); + ret = qt_safe_select(socketDescriptor + 1, &fdread, &fdwrite, 0, timeout < 0 ? 0 : &tv); if (ret <= 0) return ret; -- cgit v0.12 From cad1bf4c902899ec1a8277d46272afa23fc2b34b Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 23 Apr 2009 11:55:02 +0200 Subject: Port gui/embedded to the EINTR-safe functions. I think I found two file descriptor that aren't closed. One seems like a genuine leak, the other seems intentional. Reviewed-By: ossi --- src/gui/embedded/qkbdlinuxinput_qws.cpp | 1 + src/gui/embedded/qkbdsl5000_qws.cpp | 6 +++-- src/gui/embedded/qkbdtty_qws.cpp | 4 ++++ src/gui/embedded/qkbdvfb_qws.cpp | 9 ++++---- src/gui/embedded/qkbdvr41xx_qws.cpp | 7 +++--- src/gui/embedded/qkbdyopy_qws.cpp | 10 +++++---- src/gui/embedded/qlock.cpp | 6 +++-- src/gui/embedded/qmousebus_qws.cpp | 11 +++++----- src/gui/embedded/qmouselinuxtp_qws.cpp | 7 +++--- src/gui/embedded/qmousepc_qws.cpp | 39 +++++++++++++++++---------------- src/gui/embedded/qmousevfb_qws.cpp | 9 ++++---- src/gui/embedded/qmousevr41xx_qws.cpp | 11 +++++----- src/gui/embedded/qmouseyopy_qws.cpp | 7 +++--- src/gui/embedded/qscreenlinuxfb_qws.cpp | 20 ++++++++++------- src/gui/embedded/qsoundqss_qws.cpp | 9 ++++---- src/gui/embedded/qtransportauth_qws.cpp | 7 +++--- src/gui/embedded/qunixsocket.cpp | 18 ++++++++++----- src/gui/text/qfontdatabase_qws.cpp | 5 +++-- src/gui/text/qfontengine_qpf.cpp | 11 +++++----- src/gui/text/qfontengine_qws.cpp | 5 +++-- 20 files changed, 118 insertions(+), 84 deletions(-) diff --git a/src/gui/embedded/qkbdlinuxinput_qws.cpp b/src/gui/embedded/qkbdlinuxinput_qws.cpp index d5720f7..e552731 100644 --- a/src/gui/embedded/qkbdlinuxinput_qws.cpp +++ b/src/gui/embedded/qkbdlinuxinput_qws.cpp @@ -47,6 +47,7 @@ #include #include +#include // overrides QT_OPEN #include #include diff --git a/src/gui/embedded/qkbdsl5000_qws.cpp b/src/gui/embedded/qkbdsl5000_qws.cpp index 36cb903..cf82c10 100644 --- a/src/gui/embedded/qkbdsl5000_qws.cpp +++ b/src/gui/embedded/qkbdsl5000_qws.cpp @@ -51,6 +51,8 @@ #include "qnamespace.h" #include "qtimer.h" +#include // overrides QT_OPEN + #include #include #include @@ -207,14 +209,14 @@ QWSSL5000KeyboardHandler::QWSSL5000KeyboardHandler(const QString &device) numLock = false; sharp_kbdctl_modifstat st; - int dev = ::open(device.isEmpty()?"/dev/sharp_kbdctl":device.toLocal8Bit().constData(), O_RDWR); + int dev = QT_OPEN(device.isEmpty()?"/dev/sharp_kbdctl":device.toLocal8Bit().constData(), O_RDWR); if (dev >= 0) { memset(&st, 0, sizeof(st)); st.which = 3; int ret = ioctl(dev, SHARP_KBDCTL_GETMODIFSTAT, (char*)&st); if(!ret) numLock = (bool)st.stat; - ::close(dev); + QT_CLOSE(dev); } } diff --git a/src/gui/embedded/qkbdtty_qws.cpp b/src/gui/embedded/qkbdtty_qws.cpp index 33777eb..8c1e79b 100644 --- a/src/gui/embedded/qkbdtty_qws.cpp +++ b/src/gui/embedded/qkbdtty_qws.cpp @@ -47,6 +47,7 @@ #include #include +#include // overrides QT_OPEN #include #include @@ -213,6 +214,9 @@ QWSTtyKbPrivate::~QWSTtyKbPrivate() ::ioctl(m_tty_fd, KDSKBMODE, m_originalKbdMode); #endif tcsetattr(m_tty_fd, TCSANOW, &m_tty_attr); + + // we're leaking m_tty_fd here? + //QT_CLOSE(m_tty_fd); } } diff --git a/src/gui/embedded/qkbdvfb_qws.cpp b/src/gui/embedded/qkbdvfb_qws.cpp index 082aac1..a44183b 100644 --- a/src/gui/embedded/qkbdvfb_qws.cpp +++ b/src/gui/embedded/qkbdvfb_qws.cpp @@ -55,6 +55,7 @@ #include #include #include +#include // overrides QT_OPEN QT_BEGIN_NAMESPACE @@ -69,13 +70,13 @@ QVFbKeyboardHandler::QVFbKeyboardHandler(const QString &device) kbdBufferLen = sizeof(QVFbKeyData) * 5; kbdBuffer = new unsigned char [kbdBufferLen]; - if ((kbdFD = open(terminalName.toLatin1().constData(), O_RDONLY | O_NDELAY)) < 0) { + if ((kbdFD = QT_OPEN(terminalName.toLatin1().constData(), O_RDONLY | O_NDELAY)) < 0) { qWarning("Cannot open %s (%s)", terminalName.toLatin1().constData(), strerror(errno)); } else { // Clear pending input char buf[2]; - while (read(kbdFD, buf, 1) > 0) { } + while (QT_READ(kbdFD, buf, 1) > 0) { } notifier = new QSocketNotifier(kbdFD, QSocketNotifier::Read, this); connect(notifier, SIGNAL(activated(int)),this, SLOT(readKeyboardData())); @@ -85,7 +86,7 @@ QVFbKeyboardHandler::QVFbKeyboardHandler(const QString &device) QVFbKeyboardHandler::~QVFbKeyboardHandler() { if (kbdFD >= 0) - close(kbdFD); + QT_CLOSE(kbdFD); delete [] kbdBuffer; } @@ -94,7 +95,7 @@ void QVFbKeyboardHandler::readKeyboardData() { int n; do { - n = read(kbdFD, kbdBuffer+kbdIdx, kbdBufferLen - kbdIdx); + n = QT_READ(kbdFD, kbdBuffer+kbdIdx, kbdBufferLen - kbdIdx); if (n > 0) kbdIdx += n; } while (n > 0); diff --git a/src/gui/embedded/qkbdvr41xx_qws.cpp b/src/gui/embedded/qkbdvr41xx_qws.cpp index 03c2a67..6d8299b 100644 --- a/src/gui/embedded/qkbdvr41xx_qws.cpp +++ b/src/gui/embedded/qkbdvr41xx_qws.cpp @@ -52,6 +52,7 @@ #include #include +#include // overrides QT_OPEN QT_BEGIN_NAMESPACE @@ -95,7 +96,7 @@ QWSVr41xxKbPrivate::QWSVr41xxKbPrivate(QWSVr41xxKeyboardHandler *h, const QStrin buttonFD = -1; notifier = 0; - buttonFD = open(terminalName.toLatin1().constData(), O_RDWR | O_NDELAY, 0);; + buttonFD = QT_OPEN(terminalName.toLatin1().constData(), O_RDWR | O_NDELAY, 0);; if (buttonFD < 0) { qWarning("Cannot open %s\n", qPrintable(terminalName)); return; @@ -115,7 +116,7 @@ QWSVr41xxKbPrivate::QWSVr41xxKbPrivate(QWSVr41xxKeyboardHandler *h, const QStrin QWSVr41xxKbPrivate::~QWSVr41xxKbPrivate() { if (buttonFD > 0) { - ::close(buttonFD); + QT_CLOSE(buttonFD); buttonFD = -1; } delete notifier; @@ -127,7 +128,7 @@ void QWSVr41xxKbPrivate::readKeyboardData() { int n = 0; do { - n = read(buttonFD, kbdBuffer+kbdIdx, kbdBufferLen - kbdIdx); + n = QT_READ(buttonFD, kbdBuffer+kbdIdx, kbdBufferLen - kbdIdx); if (n > 0) kbdIdx += n; } while (n > 0); diff --git a/src/gui/embedded/qkbdyopy_qws.cpp b/src/gui/embedded/qkbdyopy_qws.cpp index 5c9d28d..edb732c 100644 --- a/src/gui/embedded/qkbdyopy_qws.cpp +++ b/src/gui/embedded/qkbdyopy_qws.cpp @@ -60,6 +60,8 @@ #include #include +#include // overrides QT_OPEN + extern "C" { int getpgid(int); } @@ -105,7 +107,7 @@ QWSYopyKbPrivate::QWSYopyKbPrivate(QWSYopyKeyboardHandler *h, const QString &dev buttonFD = -1; notifier = 0; - buttonFD = ::open(terminalName.toLatin1().constData(), O_RDWR | O_NDELAY, 0); + buttonFD = QT_OPEN(terminalName.toLatin1().constData(), O_RDWR | O_NDELAY, 0); if (buttonFD < 0) { qWarning("Cannot open %s\n", qPrintable(terminalName)); return; @@ -177,10 +179,10 @@ void QWSYopyKbPrivate::readKeyboardData() case 40: k=Qt::Key_Up; break; // prev case 45: k=Qt::Key_Down; break; // next case 35: if(!press) { - fd = open("/proc/sys/pm/sleep",O_RDWR,0); + fd = QT_OPEN("/proc/sys/pm/sleep",O_RDWR,0); if(fd >= 0) { - write(fd,&c,sizeof(c)); - close(fd); + QT_WRITE(fd,&c,sizeof(c)); + QT_CLOSE(fd); // // Updates all widgets. // diff --git a/src/gui/embedded/qlock.cpp b/src/gui/embedded/qlock.cpp index c23608f..305832c 100644 --- a/src/gui/embedded/qlock.cpp +++ b/src/gui/embedded/qlock.cpp @@ -73,6 +73,8 @@ union semun { #endif // QT_NO_QWS_MULTIPROCESS +#include // overrides QT_OPEN + #define MAX_LOCKS 200 // maximum simultaneous read locks QT_BEGIN_NAMESPACE @@ -134,7 +136,7 @@ QLock::QLock(const QString &filename, char id, bool create) #ifdef Q_NO_SEMAPHORE data->file = QString(filename+id).toLocal8Bit().constData(); for(int x = 0; x < 2; x++) { - data->id = open(data->file, O_RDWR | (x ? O_CREAT : 0), S_IRWXU); + data->id = QT_OPEN(data->file, O_RDWR | (x ? O_CREAT : 0), S_IRWXU); if(data->id != -1 || !create) { data->owned = x; break; @@ -177,7 +179,7 @@ QLock::~QLock() unlock(); #ifdef Q_NO_SEMAPHORE if(isValid()) { - close(data->id); + QT_CLOSE(data->id); if(data->owned) unlink(data->file); } diff --git a/src/gui/embedded/qmousebus_qws.cpp b/src/gui/embedded/qmousebus_qws.cpp index a88ca5b..0b674b6 100644 --- a/src/gui/embedded/qmousebus_qws.cpp +++ b/src/gui/embedded/qmousebus_qws.cpp @@ -47,6 +47,7 @@ #include "qsocketnotifier.h" #include "qapplication.h" +#include // overrides QT_OPEN #include #include @@ -119,9 +120,9 @@ QWSBusMouseHandlerPrivate::QWSBusMouseHandlerPrivate(QWSBusMouseHandler *h, mouseDev = QLatin1String("/dev/mouse"); obstate = -1; mouseFD = -1; - mouseFD = open(mouseDev.toLocal8Bit(), O_RDWR | O_NDELAY); + mouseFD = QT_OPEN(mouseDev.toLocal8Bit(), O_RDWR | O_NDELAY); if (mouseFD < 0) - mouseFD = open(mouseDev.toLocal8Bit(), O_RDONLY | O_NDELAY); + mouseFD = QT_OPEN(mouseDev.toLocal8Bit(), O_RDONLY | O_NDELAY); if (mouseFD < 0) qDebug("Cannot open %s (%s)", qPrintable(mouseDev), strerror(errno)); @@ -130,7 +131,7 @@ QWSBusMouseHandlerPrivate::QWSBusMouseHandlerPrivate(QWSBusMouseHandler *h, usleep(50000); char buf[100]; // busmouse driver will not read if bufsize < 3, YYD - while (read(mouseFD, buf, 100) > 0) { } // eat unwanted replies + while (QT_READ(mouseFD, buf, 100) > 0) { } // eat unwanted replies mouseIdx = 0; @@ -142,7 +143,7 @@ QWSBusMouseHandlerPrivate::~QWSBusMouseHandlerPrivate() { if (mouseFD >= 0) { tcflush(mouseFD,TCIFLUSH); // yyd. - close(mouseFD); + QT_CLOSE(mouseFD); } } @@ -167,7 +168,7 @@ void QWSBusMouseHandlerPrivate::readMouseData() for (;;) { if (mouseBufSize - mouseIdx < 3) break; - n = read(mouseFD, mouseBuf+mouseIdx, 3); + n = QT_READ(mouseFD, mouseBuf+mouseIdx, 3); if (n != 3) break; mouseIdx += 3; diff --git a/src/gui/embedded/qmouselinuxtp_qws.cpp b/src/gui/embedded/qmouselinuxtp_qws.cpp index 1b4d96e..e64407e 100644 --- a/src/gui/embedded/qmouselinuxtp_qws.cpp +++ b/src/gui/embedded/qmouselinuxtp_qws.cpp @@ -47,6 +47,7 @@ #include "qtimer.h" #include "qapplication.h" #include "qscreen_qws.h" +#include // overrides QT_OPEN #include #include @@ -190,7 +191,7 @@ QWSLinuxTPMouseHandlerPrivate::QWSLinuxTPMouseHandlerPrivate(QWSLinuxTPMouseHand } else { mousedev = device; } - if ((mouseFD = open(mousedev.toLatin1().constData(), O_RDONLY | O_NDELAY)) < 0) { + if ((mouseFD = QT_OPEN(mousedev.toLatin1().constData(), O_RDONLY | O_NDELAY)) < 0) { qWarning("Cannot open %s (%s)", qPrintable(mousedev), strerror(errno)); return; } @@ -205,7 +206,7 @@ QWSLinuxTPMouseHandlerPrivate::QWSLinuxTPMouseHandlerPrivate(QWSLinuxTPMouseHand QWSLinuxTPMouseHandlerPrivate::~QWSLinuxTPMouseHandlerPrivate() { if (mouseFD >= 0) - close(mouseFD); + QT_CLOSE(mouseFD); } void QWSLinuxTPMouseHandlerPrivate::suspend() @@ -233,7 +234,7 @@ void QWSLinuxTPMouseHandlerPrivate::readMouseData() int n; do { - n = read(mouseFD, mouseBuf+mouseIdx, mouseBufSize-mouseIdx); + n = QT_READ(mouseFD, mouseBuf+mouseIdx, mouseBufSize-mouseIdx); if (n > 0) mouseIdx += n; } while (n > 0 && mouseIdx < mouseBufSize); diff --git a/src/gui/embedded/qmousepc_qws.cpp b/src/gui/embedded/qmousepc_qws.cpp index a9f2bc8..317bb8a 100644 --- a/src/gui/embedded/qmousepc_qws.cpp +++ b/src/gui/embedded/qmousepc_qws.cpp @@ -55,6 +55,7 @@ #include "qfile.h" #include "qtextstream.h" #include "qstringlist.h" +#include // overrides QT_OPEN #include #include @@ -107,7 +108,7 @@ public: { if (fd != f) { f = fd; - close(fd); + QT_CLOSE(fd); } } @@ -170,7 +171,7 @@ public: } static const uchar initseq[] = { 243, 200, 243, 100, 243, 80 }; static const uchar query[] = { 0xf2 }; - if (write(fd, initseq, sizeof(initseq))!=sizeof(initseq)) { + if (QT_WRITE(fd, initseq, sizeof(initseq))!=sizeof(initseq)) { badness = 100; return; } @@ -180,12 +181,12 @@ public: perror("QWSPcMouseSubHandler_intellimouse: post-init tcflush"); #endif } - if (write(fd, query, sizeof(query))!=sizeof(query)) { + if (QT_WRITE(fd, query, sizeof(query))!=sizeof(query)) { badness = 100; return; } usleep(10000); - n = read(fd, reply, 20); + n = QT_READ(fd, reply, 20); if (n > 0) { goodness = 10; switch (reply[n-1]) { @@ -256,13 +257,13 @@ public: perror("QWSPcMouseSubHandler_mouseman: initial tcflush"); #endif } - write(fd,"",1); + QT_WRITE(fd,"",1); usleep(50000); - write(fd,"@EeI!",5); + QT_WRITE(fd,"@EeI!",5); usleep(10000); static const char ibuf[] = { 246, 244 }; - write(fd,ibuf,1); - write(fd,ibuf+1,1); + QT_WRITE(fd,ibuf,1); + QT_WRITE(fd,ibuf+1,1); if (tcflush(fd,TCIOFLUSH) == -1) { #ifdef QWS_MOUSE_DEBUG perror("QWSPcMouseSubHandler_mouseman: tcflush"); @@ -271,7 +272,7 @@ public: usleep(10000); char buf[100]; - while (read(fd, buf, 100) > 0) { } // eat unwanted replies + while (QT_READ(fd, buf, 100) > 0) { } // eat unwanted replies } int tryData() @@ -350,7 +351,7 @@ private: for (int n = 0; n < 4; n++) { setflags(CSTOPB | speed[n]); - write(fd, "*q", 2); + QT_WRITE(fd, "*q", 2); usleep(10000); } } @@ -369,7 +370,7 @@ public: { setflags(B1200|CS8|CSTOPB); // 60Hz - if (write(fd, "R", 1)!=1) { + if (QT_WRITE(fd, "R", 1)!=1) { badness = 100; return; } @@ -418,7 +419,7 @@ public: { setflags(B1200|CS7); // 60Hz - if (write(fd, "R", 1)!=1) { + if (QT_WRITE(fd, "R", 1)!=1) { badness = 100; return; } @@ -648,25 +649,25 @@ void QWSPcMouseHandlerPrivate::openDevices() if (drv == QLatin1String("intellimouse")) { if (dev.isEmpty()) dev = "/dev/psaux"; - fd = open(dev, O_RDWR | O_NDELAY); + fd = QT_OPEN(dev, O_RDWR | O_NDELAY); if (fd >= 0) sub[nsub++] = new QWSPcMouseSubHandler_intellimouse(fd); } else if (drv == QLatin1String("microsoft")) { if (dev.isEmpty()) dev = "/dev/ttyS0"; - fd = open(dev, O_RDWR | O_NDELAY); + fd = QT_OPEN(dev, O_RDWR | O_NDELAY); if (fd >= 0) sub[nsub++] = new QWSPcMouseSubHandler_ms(fd); } else if (drv == QLatin1String("mousesystems")) { if (dev.isEmpty()) dev = "/dev/ttyS0"; - fd = open(dev, O_RDWR | O_NDELAY); + fd = QT_OPEN(dev, O_RDWR | O_NDELAY); if (fd >= 0) sub[nsub++] = new QWSPcMouseSubHandler_mousesystems(fd); } else if (drv == QLatin1String("mouseman")) { if (dev.isEmpty()) dev = "/dev/psaux"; - fd = open(dev, O_RDWR | O_NDELAY); + fd = QT_OPEN(dev, O_RDWR | O_NDELAY); if (fd >= 0) sub[nsub++] = new QWSPcMouseSubHandler_mouseman(fd); } @@ -677,12 +678,12 @@ void QWSPcMouseHandlerPrivate::openDevices() dev.constData(), strerror(errno)); } else { // Try automatically - fd = open("/dev/psaux", O_RDWR | O_NDELAY); + fd = QT_OPEN("/dev/psaux", O_RDWR | O_NDELAY); if (fd >= 0) { sub[nsub++] = new QWSPcMouseSubHandler_intellimouse(fd); notify(fd); } - fd = open("/dev/input/mice", O_RDWR | O_NDELAY); + fd = QT_OPEN("/dev/input/mice", O_RDWR | O_NDELAY); if (fd >= 0) { sub[nsub++] = new QWSPcMouseSubHandler_intellimouse(fd); notify(fd); @@ -694,7 +695,7 @@ void QWSPcMouseHandlerPrivate::openDevices() #if 0 const char fn[4][11] = { "/dev/ttyS0", "/dev/ttyS1", "/dev/ttyS2", "/dev/ttyS3" }; for (int ch = 0; ch < 4; ++ch) { - fd = open(fn[ch], O_RDWR | O_NDELAY); + fd = QT_OPEN(fn[ch], O_RDWR | O_NDELAY); if (fd >= 0) { //sub[nsub++] = new QWSPcMouseSubHandler_intellimouse(fd); sub[nsub++] = new QWSPcMouseSubHandler_mousesystems(fd); diff --git a/src/gui/embedded/qmousevfb_qws.cpp b/src/gui/embedded/qmousevfb_qws.cpp index 17d051f..dd553bc 100644 --- a/src/gui/embedded/qmousevfb_qws.cpp +++ b/src/gui/embedded/qmousevfb_qws.cpp @@ -54,6 +54,7 @@ #include #include #include +#include // overrides QT_OPEN QT_BEGIN_NAMESPACE @@ -64,7 +65,7 @@ QVFbMouseHandler::QVFbMouseHandler(const QString &driver, const QString &device) if (device.isEmpty()) mouseDev = QLatin1String("/dev/vmouse"); - mouseFD = open(mouseDev.toLatin1().constData(), O_RDWR | O_NDELAY); + mouseFD = QT_OPEN(mouseDev.toLatin1().constData(), O_RDWR | O_NDELAY); if (mouseFD == -1) { perror("QVFbMouseHandler::QVFbMouseHandler"); qWarning("QVFbMouseHander: Unable to open device %s", @@ -74,7 +75,7 @@ QVFbMouseHandler::QVFbMouseHandler(const QString &driver, const QString &device) // Clear pending input char buf[2]; - while (read(mouseFD, buf, 1) > 0) { } + while (QT_READ(mouseFD, buf, 1) > 0) { } mouseIdx = 0; @@ -85,7 +86,7 @@ QVFbMouseHandler::QVFbMouseHandler(const QString &driver, const QString &device) QVFbMouseHandler::~QVFbMouseHandler() { if (mouseFD >= 0) - close(mouseFD); + QT_CLOSE(mouseFD); } void QVFbMouseHandler::resume() @@ -102,7 +103,7 @@ void QVFbMouseHandler::readMouseData() { int n; do { - n = read(mouseFD, mouseBuf+mouseIdx, mouseBufSize-mouseIdx); + n = QT_READ(mouseFD, mouseBuf+mouseIdx, mouseBufSize-mouseIdx); if (n > 0) mouseIdx += n; } while (n > 0); diff --git a/src/gui/embedded/qmousevr41xx_qws.cpp b/src/gui/embedded/qmousevr41xx_qws.cpp index 8748055..b7491d9 100644 --- a/src/gui/embedded/qmousevr41xx_qws.cpp +++ b/src/gui/embedded/qmousevr41xx_qws.cpp @@ -49,6 +49,7 @@ #include "qscreen_qws.h" #include #include +#include // overrides QT_OPEN #include #include @@ -144,7 +145,7 @@ QWSVr41xxMouseHandlerPrivate::QWSVr41xxMouseHandlerPrivate(QWSVr41xxMouseHandler else dev = options.first(); - if ((mouseFD = open(dev.toLocal8Bit().constData(), O_RDONLY)) < 0) { + if ((mouseFD = QT_OPEN(dev.toLocal8Bit().constData(), O_RDONLY)) < 0) { qWarning("Cannot open %s (%s)", qPrintable(dev), strerror(errno)); return; } @@ -167,7 +168,7 @@ QWSVr41xxMouseHandlerPrivate::QWSVr41xxMouseHandlerPrivate(QWSVr41xxMouseHandler QWSVr41xxMouseHandlerPrivate::~QWSVr41xxMouseHandlerPrivate() { if (mouseFD >= 0) - close(mouseFD); + QT_CLOSE(mouseFD); } void QWSVr41xxMouseHandlerPrivate::suspend() @@ -190,9 +191,9 @@ void QWSVr41xxMouseHandlerPrivate::sendRelease() bool QWSVr41xxMouseHandlerPrivate::getSample() { - const int n = read(mouseFD, - reinterpret_cast(currSample) + currLength, - sizeof(currSample) - currLength); + const int n = QT_READ(mouseFD, + reinterpret_cast(currSample) + currLength, + sizeof(currSample) - currLength); if (n > 0) currLength += n; diff --git a/src/gui/embedded/qmouseyopy_qws.cpp b/src/gui/embedded/qmouseyopy_qws.cpp index 7b1141a..3a541d3 100644 --- a/src/gui/embedded/qmouseyopy_qws.cpp +++ b/src/gui/embedded/qmouseyopy_qws.cpp @@ -46,6 +46,7 @@ #include "qsocketnotifier.h" #include "qapplication.h" #include "qscreen_qws.h" +#include // overrides QT_OPEN #include #include @@ -103,7 +104,7 @@ void QWSYopyMouseHandler::suspend() QWSYopyMouseHandlerPrivate::QWSYopyMouseHandlerPrivate(QWSYopyMouseHandler *h) : handler(h) { - if ((mouseFD = open("/dev/ts", O_RDONLY)) < 0) { + if ((mouseFD = QT_OPEN("/dev/ts", O_RDONLY)) < 0) { qWarning("Cannot open /dev/ts (%s)", strerror(errno)); return; } else { @@ -118,7 +119,7 @@ QWSYopyMouseHandlerPrivate::QWSYopyMouseHandlerPrivate(QWSYopyMouseHandler *h) QWSYopyMouseHandlerPrivate::~QWSYopyMouseHandlerPrivate() { if (mouseFD >= 0) - close(mouseFD); + QT_CLOSE(mouseFD); } #define YOPY_XPOS(d) (d[1]&0x3FF) @@ -156,7 +157,7 @@ void QWSYopyMouseHandlerPrivate::readMouseData() int ret; - ret=read(mouseFD,&yopDat,sizeof(yopDat)); + ret=QT_READ(mouseFD,&yopDat,sizeof(yopDat)); if(ret) { data.status= (YOPY_PRES(yopDat)) ? 1 : 0; diff --git a/src/gui/embedded/qscreenlinuxfb_qws.cpp b/src/gui/embedded/qscreenlinuxfb_qws.cpp index 42c4fcd..2845842 100644 --- a/src/gui/embedded/qscreenlinuxfb_qws.cpp +++ b/src/gui/embedded/qscreenlinuxfb_qws.cpp @@ -46,6 +46,7 @@ #include "qwsdisplay_qws.h" #include "qpixmap.h" #include +#include // overrides QT_OPEN #include #include @@ -122,12 +123,12 @@ void QLinuxFbScreenPrivate::openTty() if (ttyDevice.isEmpty()) { for (const char * const *dev = devs; *dev; ++dev) { - ttyfd = ::open(*dev, O_RDWR); + ttyfd = QT_OPEN(*dev, O_RDWR); if (ttyfd != -1) break; } } else { - ttyfd = ::open(ttyDevice.toAscii().constData(), O_RDWR); + ttyfd = QT_OPEN(ttyDevice.toAscii().constData(), O_RDWR); } if (ttyfd == -1) @@ -144,7 +145,7 @@ void QLinuxFbScreenPrivate::openTty() // No blankin' screen, no blinkin' cursor!, no cursor! const char termctl[] = "\033[9;0]\033[?33l\033[?25l\033[?1c"; - ::write(ttyfd, termctl, sizeof(termctl)); + QT_WRITE(ttyfd, termctl, sizeof(termctl)); } void QLinuxFbScreenPrivate::closeTty() @@ -157,9 +158,9 @@ void QLinuxFbScreenPrivate::closeTty() // Blankin' screen, blinkin' cursor! const char termctl[] = "\033[9;15]\033[?33h\033[?25h\033[?0c"; - ::write(ttyfd, termctl, sizeof(termctl)); + QT_WRITE(ttyfd, termctl, sizeof(termctl)); - ::close(ttyfd); + QT_CLOSE(ttyfd); ttyfd = -1; } @@ -281,7 +282,7 @@ bool QLinuxFbScreen::connect(const QString &displaySpec) dev = QLatin1String("/dev/fb0"); if (access(dev.toLatin1().constData(), R_OK|W_OK) == 0) - d_ptr->fd = open(dev.toLatin1().constData(), O_RDWR); + d_ptr->fd = QT_OPEN(dev.toLatin1().constData(), O_RDWR); if (d_ptr->fd == -1) { if (QApplication::type() == QApplication::GuiServer) { perror("QScreenLinuxFb::connect"); @@ -289,7 +290,7 @@ bool QLinuxFbScreen::connect(const QString &displaySpec) return false; } if (access(dev.toLatin1().constData(), R_OK) == 0) - d_ptr->fd = open(dev.toLatin1().constData(), O_RDONLY); + d_ptr->fd = QT_OPEN(dev.toLatin1().constData(), O_RDONLY); } fb_fix_screeninfo finfo; @@ -681,7 +682,7 @@ bool QLinuxFbScreen::initDevice() #ifdef __i386__ // Now init mtrr if(!::getenv("QWS_NOMTRR")) { - int mfd=open("/proc/mtrr",O_WRONLY,0); + int mfd=QT_OPEN("/proc/mtrr",O_WRONLY,0); // MTRR entry goes away when file is closed - i.e. // hopefully when QWS is killed if(mfd != -1) { @@ -702,6 +703,9 @@ bool QLinuxFbScreen::initDevice() //sentry.base,sentry.size,strerror(errno)); } } + + // Should we close mfd here? + //QT_CLOSE(mfd); } #endif if ((vinfo.bits_per_pixel==8) || (vinfo.bits_per_pixel==4) || (finfo.visual==FB_VISUAL_DIRECTCOLOR)) diff --git a/src/gui/embedded/qsoundqss_qws.cpp b/src/gui/embedded/qsoundqss_qws.cpp index ac0ac9d..a45d0fe 100644 --- a/src/gui/embedded/qsoundqss_qws.cpp +++ b/src/gui/embedded/qsoundqss_qws.cpp @@ -53,6 +53,7 @@ #include #include #include +#include // overrides QT_OPEN #include #include @@ -1137,7 +1138,7 @@ void QWSSoundServerPrivate::sendCompletedSignals() int QWSSoundServerPrivate::openFile(int wid, int sid, const QString& filename) { stopFile(wid, sid); // close and re-open. - int f = ::open(QFile::encodeName(filename), O_RDONLY|O_NONBLOCK); + int f = QT_OPEN(QFile::encodeName(filename), O_RDONLY|O_NONBLOCK); if (f == -1) { // XXX check ferror, check reason. qDebug("Failed opening \"%s\"",filename.toLatin1().data()); @@ -1157,7 +1158,7 @@ bool QWSSoundServerPrivate::openDevice() { if (fd < 0) { if( silent ) { - fd = ::open( "/dev/null", O_WRONLY ); + fd = QT_OPEN( "/dev/null", O_WRONLY ); // Emulate write to audio device int delay = 1000*(sound_buffer_size>>(sound_stereo+sound_16bit))/sound_speed/2; timerId = startTimer(delay); @@ -1168,7 +1169,7 @@ bool QWSSoundServerPrivate::openDevice() // Don't block open right away. // bool openOkay = false; - if ((fd = ::open("/dev/dsp", O_WRONLY|O_NONBLOCK)) != -1) { + if ((fd = QT_OPEN("/dev/dsp", O_WRONLY|O_NONBLOCK)) != -1) { int flags = fcntl(fd, F_GETFL); flags &= ~O_NONBLOCK; openOkay = (fcntl(fd, F_SETFL, flags) == 0); @@ -1222,7 +1223,7 @@ bool QWSSoundServerPrivate::openDevice() // // Check system volume // - int mixerHandle = ::open( "/dev/mixer", O_RDWR|O_NONBLOCK ); + int mixerHandle = QT_OPEN( "/dev/mixer", O_RDWR|O_NONBLOCK ); if ( mixerHandle >= 0 ) { int volume; ioctl( mixerHandle, MIXER_READ(0), &volume ); diff --git a/src/gui/embedded/qtransportauth_qws.cpp b/src/gui/embedded/qtransportauth_qws.cpp index 05dce11..8523e27 100644 --- a/src/gui/embedded/qtransportauth_qws.cpp +++ b/src/gui/embedded/qtransportauth_qws.cpp @@ -56,6 +56,7 @@ #include "qlibraryinfo.h" #include "qfile.h" #include "qdebug.h" +#include // overrides QT_OPEN #include #include @@ -572,7 +573,7 @@ bool QTransportAuth::authorizeRequest( QTransportAuth::Data &d, const QString &r //get cmdline from proc/pid/cmdline snprintf( cmdlinePath, BUF_SIZE, "/proc/%d/cmdline", d.processId ); - int cmdlineFd = open( cmdlinePath, O_RDONLY ); + int cmdlineFd = QT_OPEN( cmdlinePath, O_RDONLY ); if ( cmdlineFd == -1 ) { qWarning( "SXE:- Error encountered in opening /proc/%u/cmdline: %s", @@ -581,13 +582,13 @@ bool QTransportAuth::authorizeRequest( QTransportAuth::Data &d, const QString &r } else { - if ( -1 == ::read(cmdlineFd, cmdline, BUF_SIZE - 1 ) ) + if ( -1 == QT_READ(cmdlineFd, cmdline, BUF_SIZE - 1 ) ) { qWarning( "SXE:- Error encountered in reading /proc/%u/cmdline : %s", d.processId, strerror(errno) ); snprintf( cmdline, BUF_SIZE, "%s", "Unknown" ); } - close( cmdlineFd ); + QT_CLOSE( cmdlineFd ); } syslog( LOG_ERR | LOG_LOCAL6, "%s // PID:%u // ProgId:%u // Exe:%s // Request:%s // Cmdline:%s", diff --git a/src/gui/embedded/qunixsocket.cpp b/src/gui/embedded/qunixsocket.cpp index 070d3cf..57a4a11 100644 --- a/src/gui/embedded/qunixsocket.cpp +++ b/src/gui/embedded/qunixsocket.cpp @@ -46,6 +46,7 @@ #include #include #include +#include "private/qcore_unix_p.h" // overrides QT_OPEN #ifdef QUNIXSOCKET_DEBUG #include @@ -131,7 +132,7 @@ struct QUnixSocketRightsPrivate : public QSharedData #ifdef QUNIXSOCKET_DEBUG int closerv = #endif - ::close(fd); + QT_CLOSE(fd); #ifdef QUNIXSOCKET_DEBUG if(0 != closerv) { qDebug() << "QUnixSocketRightsPrivate: Unable to close managed" @@ -162,7 +163,7 @@ QUnixSocketRights::QUnixSocketRights(int fd) if(-1 == fd) { d->fd = -1; } else { - d->fd = ::dup(fd); + d->fd = qt_safe_dup(fd); #ifdef QUNIXSOCKET_DEBUG if(-1 == d->fd) { qDebug() << "QUnixSocketRights: Unable to duplicate fd " @@ -232,7 +233,7 @@ int QUnixSocketRights::dupFd() const { if(-1 == d->fd) return -1; - int rv = ::dup(d->fd); + int rv = qt_safe_dup(d->fd); #ifdef QUNIXSOCKET_DEBUG if(-1 == rv) @@ -825,7 +826,7 @@ public: int numFds = (h->cmsg_len - CMSG_LEN(0)) / sizeof(int); for(int ii = 0; ii < numFds; ++ii) - ::close(fds[ii]); + QT_CLOSE(fds[ii]); } h = (::cmsghdr *)CMSG_NXTHDR(&(message), h); @@ -1017,7 +1018,7 @@ connect_error: // Cleanup failed connection #ifdef QUNIXSOCKET_DEBUG int closerv = #endif - ::close(d->fd); + QT_CLOSE(d->fd); #ifdef QUNIXSOCKET_DEBUG if(0 != closerv) { qDebug() << "QUnixSocket: Unable to close file descriptor after " @@ -1762,7 +1763,12 @@ void QUnixSocketPrivate::readActivated() message.msg_controllen = ancillaryBufferCapacity(); message.msg_control = ancillaryBuffer; - int recvrv = ::recvmsg(fd, &message, 0); + int flags = 0; +#ifdef MSG_CMSG_CLOEXEC + flags = MSG_CMSG_CLOEXEC; +#endif + + int recvrv = ::recvmsg(fd, &message, flags); #ifdef QUNIXSOCKET_DEBUG qDebug() << "QUnixSocket: Received message (" << recvrv << ')'; #endif diff --git a/src/gui/text/qfontdatabase_qws.cpp b/src/gui/text/qfontdatabase_qws.cpp index 2c359ba..d348e1b 100644 --- a/src/gui/text/qfontdatabase_qws.cpp +++ b/src/gui/text/qfontdatabase_qws.cpp @@ -55,6 +55,7 @@ #endif #include "qfontengine_qpf_p.h" #include "private/qfactoryloader_p.h" +#include "private/qcore_unix_p.h" // overrides QT_OPEN #include "qabstractfontengine_qws.h" #include "qabstractfontengine_p.h" #include @@ -128,7 +129,7 @@ void QFontDatabasePrivate::addQPF2File(const QByteArray &file) struct stat st; if (stat(file.constData(), &st)) return; - int f = ::open(file, O_RDONLY, 0); + int f = QT_OPEN(file, O_RDONLY, 0); if (f < 0) return; const uchar *data = (const uchar *)mmap(0, st.st_size, PROT_READ, MAP_SHARED, f, 0); @@ -176,7 +177,7 @@ void QFontDatabasePrivate::addQPF2File(const QByteArray &file) #endif } #ifndef QT_FONTS_ARE_RESOURCES - ::close(f); + QT_CLOSE(f); #endif } #endif diff --git a/src/gui/text/qfontengine_qpf.cpp b/src/gui/text/qfontengine_qpf.cpp index 2df4095..b255694 100644 --- a/src/gui/text/qfontengine_qpf.cpp +++ b/src/gui/text/qfontengine_qpf.cpp @@ -51,6 +51,7 @@ #if !defined(QT_NO_FREETYPE) #include "private/qfontengine_ft_p.h" #endif +#include "private/qcore_unix_p.h" // overrides QT_OPEN // for mmap #include @@ -252,7 +253,7 @@ QList QFontEngineQPF::cleanUpAfterClientCrash(const QList &cras for (int i = 0; i < int(dir.count()); ++i) { const QByteArray fileName = QFile::encodeName(dir.absoluteFilePath(dir[i])); - int fd = ::open(fileName.constData(), O_RDONLY, 0); + int fd = QT_OPEN(fileName.constData(), O_RDONLY, 0); if (fd >= 0) { void *header = ::mmap(0, sizeof(QFontEngineQPF::Header), PROT_READ, MAP_SHARED, fd, 0); if (header && header != MAP_FAILED) { @@ -265,7 +266,7 @@ QList QFontEngineQPF::cleanUpAfterClientCrash(const QList &cras ::munmap(header, sizeof(QFontEngineQPF::Header)); } - ::close(fd); + QT_CLOSE(fd); } } if (!removedFonts.isEmpty()) @@ -331,15 +332,15 @@ QFontEngineQPF::QFontEngineQPF(const QFontDef &def, int fileDescriptor, QFontEng qDebug() << "found existing qpf:" << fileName; #endif if (::access(encodedName, W_OK | R_OK) == 0) - fd = ::open(encodedName, O_RDWR, 0); + fd = QT_OPEN(encodedName, O_RDWR, 0); else if (::access(encodedName, R_OK) == 0) - fd = ::open(encodedName, O_RDONLY, 0); + fd = QT_OPEN(encodedName, O_RDONLY, 0); } else { #if defined(DEBUG_FONTENGINE) qDebug() << "creating qpf on the fly:" << fileName; #endif if (::access(QFile::encodeName(qws_fontCacheDir()), W_OK) == 0) { - fd = ::open(encodedName, O_RDWR | O_EXCL | O_CREAT, 0644); + fd = QT_OPEN(encodedName, O_RDWR | O_EXCL | O_CREAT, 0644); QBuffer buffer; buffer.open(QIODevice::ReadWrite); diff --git a/src/gui/text/qfontengine_qws.cpp b/src/gui/text/qfontengine_qws.cpp index 6fb4f15..70ce8f9 100644 --- a/src/gui/text/qfontengine_qws.cpp +++ b/src/gui/text/qfontengine_qws.cpp @@ -47,6 +47,7 @@ #include #include #include "qtextengine_p.h" +#include "private/qcore_unix_p.h" // overrides QT_OPEN #include @@ -387,7 +388,7 @@ QFontEngineQPF1::QFontEngineQPF1(const QFontDef&, const QString &fn) { cache_cost = 1; - int f = ::open( QFile::encodeName(fn), O_RDONLY, 0); + int f = QT_OPEN( QFile::encodeName(fn), O_RDONLY, 0); Q_ASSERT(f>=0); QT_STATBUF st; if ( QT_FSTAT( f, &st ) ) @@ -406,7 +407,7 @@ QFontEngineQPF1::QFontEngineQPF1(const QFontDef&, const QString &fn) #endif if ( !data || data == (uchar*)MAP_FAILED ) qFatal("Failed to mmap %s",QFile::encodeName(fn).data()); - ::close(f); + QT_CLOSE(f); d = new QFontEngineQPF1Data; memcpy(reinterpret_cast(&d->fm),data,sizeof(d->fm)); -- cgit v0.12 From d7d0d20469d447933c827d169651c3751c7069ad Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 23 Apr 2009 20:07:34 +0200 Subject: Add the support for the EINTR- and CLOEXEC-safe network calls too. The SOCK_NONBLOCK, SOCK_CLOEXEC and accept4(2) calls are Linux-specific. Other platforms get the same behaviour through emulation. Reviewed-By: ossi --- src/network/socket/qnet_unix_p.h | 153 +++++++++++++++++++++++++++++++++++++++ src/network/socket/socket.pri | 3 +- 2 files changed, 155 insertions(+), 1 deletion(-) create mode 100644 src/network/socket/qnet_unix_p.h diff --git a/src/network/socket/qnet_unix_p.h b/src/network/socket/qnet_unix_p.h new file mode 100644 index 0000000..5256131 --- /dev/null +++ b/src/network/socket/qnet_unix_p.h @@ -0,0 +1,153 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtNetwork module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QNET_UNIX_P_H +#define QNET_UNIX_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of Qt code on Unix. This header file may change from version to +// version to version without notice, or even be removed. +// +// We mean it. +// + +#include "private/qcore_unix_p.h" + +#include +#include +#include + +QT_BEGIN_NAMESPACE + +// Almost always the same. If not, specify in qplatformdefs.h. +#if !defined(QT_SOCKOPTLEN_T) +# define QT_SOCKOPTLEN_T QT_SOCKLEN_T +#endif + +// UnixWare 7 redefines socket -> _socket +static inline int qt_safe_socket(int domain, int type, int protocol, int flags = 0) +{ + Q_ASSERT((flags & ~O_NONBLOCK) == 0); + + register int fd; +#ifdef SOCK_CLOEXEC + int newtype = type | SOCK_CLOEXEC; + if (flags & O_NONBLOCK) + newtype |= SOCK_NONBLOCK; + fd = ::socket(domain, newtype, protocol); + if (fd != -1 || errno != EINVAL) + return fd; +#endif + + fd = ::socket(domain, type, protocol); + if (fd == -1) + return -1; + + ::fcntl(fd, F_SETFD, FD_CLOEXEC); + + // set non-block too? + if (flags & O_NONBLOCK) + ::fcntl(fd, F_SETFL, ::fcntl(fd, F_GETFL) | O_NONBLOCK); + + return fd; +} + +// Tru64 redefines accept -> _accept with _XOPEN_SOURCE_EXTENDED +static inline int qt_safe_accept(int s, struct sockaddr *addr, QT_SOCKLEN_T *addrlen, int flags = 0) +{ + Q_ASSERT((flags & ~O_NONBLOCK) == 0); + + register int fd; +#if 0 // no released version of glibc contains accept4 yet + // use accept4 + int sockflags = SOCK_CLOEXEC; + if (flags & O_NONBLOCK) + sockflags |= SOCK_NONBLOCK; + fd = ::accept4(s, addr, static_cast(addrlen), sockflags); + if (fd != -1 || !(errno == ENOSYS || errno == EINVAL)) + return fd; +#endif + + fd = ::accept(s, addr, static_cast(addrlen)); + if (fd == -1) + return -1; + + ::fcntl(fd, F_SETFD, FD_CLOEXEC); + + // set non-block too? + if (flags & O_NONBLOCK) + ::fcntl(fd, F_SETFL, ::fcntl(fd, F_GETFL) | O_NONBLOCK); + + return fd; +} + +// UnixWare 7 redefines listen -> _listen +static inline int qt_safe_listen(int s, int backlog) +{ + return ::listen(s, backlog); +} + +static inline int qt_safe_connect(int sockfd, const struct sockaddr *addr, QT_SOCKLEN_T addrlen) +{ + register int ret; + EINTR_LOOP(ret, QT_SOCKET_CONNECT(sockfd, addr, addrlen)); + return ret; +} +#undef QT_SOCKET_CONNECT +#define QT_SOCKET_CONNECT qt_safe_connect + +#if defined(socket) +# undef socket +#endif +#if defined(accept) +# undef accept +#endif +#if defined(listen) +# undef listen +#endif + +QT_END_NAMESPACE + +#endif // QNET_UNIX_P_H diff --git a/src/network/socket/socket.pri b/src/network/socket/socket.pri index b1fe64a..17e49d2 100644 --- a/src/network/socket/socket.pri +++ b/src/network/socket/socket.pri @@ -28,7 +28,8 @@ SOURCES += socket/qabstractsocketengine.cpp \ unix:SOURCES += socket/qnativesocketengine_unix.cpp \ socket/qlocalsocket_unix.cpp \ socket/qlocalserver_unix.cpp - +unix:HEADERS += \ + socket/qnet_unix_p.h win32:SOURCES += socket/qnativesocketengine_win.cpp \ socket/qlocalsocket_win.cpp \ -- cgit v0.12 From 0b757d0c1b6f64d17086621ec692369d37fd62fc Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 23 Apr 2009 20:07:47 +0200 Subject: Use the safe versions of the network system calls I have just added. Reviewed-By: ossi --- src/corelib/kernel/qcore_unix.cpp | 63 +++++++++++++++++++++++++ src/corelib/kernel/qcore_unix_p.h | 13 ++++- src/network/socket/qlocalserver_unix.cpp | 9 ++-- src/network/socket/qlocalsocket_p.h | 37 --------------- src/network/socket/qlocalsocket_unix.cpp | 5 +- src/network/socket/qnativesocketengine_unix.cpp | 8 ++-- src/network/socket/qnet_unix_p.h | 2 +- 7 files changed, 88 insertions(+), 49 deletions(-) diff --git a/src/corelib/kernel/qcore_unix.cpp b/src/corelib/kernel/qcore_unix.cpp index ffaf958..2549f77 100644 --- a/src/corelib/kernel/qcore_unix.cpp +++ b/src/corelib/kernel/qcore_unix.cpp @@ -119,3 +119,66 @@ int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept, } QT_END_NAMESPACE + +#ifdef Q_OS_LINUX +// Don't wait for libc to supply the calls we need +// Make syscalls directly + +# if defined(__GLIBC__) && (__GLIBC__ * 0x100 + __GLIBC_MINOR__) >= 0x0204 +// glibc 2.4 has syscall(...) +# include +# include +# else +// no syscall(...) +static inline int syscall(...) { errno = ENOSYS; return -1;} +# endif + +# ifndef __NR_dup3 +# if defined(__i386__) +# define __NR_dup3 330 +# define __NR_pipe2 331 +# elif defined(__x86_64__) +# define __NR_accept4 288 +# define __NR_dup3 292 +# define __NR_pipe2 293 +# elif defined(__ia64__) +# define __NR_accept4 -1 +# define __NR_dup3 1316 +# define __NR_pipe2 1317 +# else +// set the syscalls to absurd numbers so that they'll cause ENOSYS errors +# warning "Please port the pipe2/dup3/accept4 code to this platform" +# define __NR_accept4 -1 +# define __NR_dup3 -1 +# define __NR_pipe2 -1 +# endif +# endif + +QT_BEGIN_NAMESPACE +namespace QtLibcSupplement { + int pipe2(int pipes[], int flags) + { + return syscall(__NR_pipe2, pipes, flags); + } + + int dup3(int oldfd, int newfd, int flags) + { + return syscall(__NR_dup3, oldfd, newfd, flags); + } + + int accept4(int s, sockaddr *addr, QT_SOCKLEN_T *addrlen, int flags) + { +# if defined(__NR_socketcall) + // This platform uses socketcall() instead of raw syscalls + // the SYS_ACCEPT4 number is cross-platform: 18 + return syscall(__NR_socketcall, 18, &s); +# else + return syscall(__NR_accept4, s, addr, addrlen, flags); +# endif + + Q_UNUSED(addr); Q_UNUSED(addrlen); Q_UNUSED(flags); // they're actually used + } +} +QT_END_NAMESPACE +#endif // Q_OS_LINUX + diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h index 4e3158a..6ae4ff0 100644 --- a/src/corelib/kernel/qcore_unix_p.h +++ b/src/corelib/kernel/qcore_unix_p.h @@ -67,10 +67,21 @@ #include #include +struct sockaddr; + QT_BEGIN_NAMESPACE -#if defined(Q_OS_LINUX) && defined(__GLIBC__) && (__GLIBC__ * 0x100 + __GLIBC_MINOR__) >= 0x0209 +#if defined(Q_OS_LINUX) && defined(__GLIBC__) && (__GLIBC__ * 0x100 + __GLIBC_MINOR__) >= 0x0204 +// Linux supports thread-safe FD_CLOEXEC # define QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC 1 + +namespace QtLibcSupplement { + Q_CORE_EXPORT int accept4(int, sockaddr *, QT_SOCKLEN_T *, int flags); + Q_CORE_EXPORT int dup3(int oldfd, int newfd, int flags); + Q_CORE_EXPORT int pipe2(int pipes[], int flags); +} + +using namespace QtLibcSupplement; #else # define QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC 0 #endif diff --git a/src/network/socket/qlocalserver_unix.cpp b/src/network/socket/qlocalserver_unix.cpp index 1cb804a..c2e05cd 100644 --- a/src/network/socket/qlocalserver_unix.cpp +++ b/src/network/socket/qlocalserver_unix.cpp @@ -43,6 +43,7 @@ #include "qlocalserver_p.h" #include "qlocalsocket.h" #include "qlocalsocket_p.h" +#include "qnet_unix_p.h" #ifndef QT_NO_LOCALSERVER @@ -88,7 +89,7 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName) serverName = requestedServerName; // create the unix socket - listenSocket = qSocket(PF_UNIX, SOCK_STREAM, 0); + listenSocket = qt_safe_socket(PF_UNIX, SOCK_STREAM, 0); if (-1 == listenSocket) { setError(QLatin1String("QLocalServer::listen")); closeServer(); @@ -107,7 +108,7 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName) fullServerName.toLatin1().size() + 1); // bind - if(-1 == qBind(listenSocket, (sockaddr *)&addr, sizeof(sockaddr_un))) { + if(-1 == QT_SOCKET_BIND(listenSocket, (sockaddr *)&addr, sizeof(sockaddr_un))) { setError(QLatin1String("QLocalServer::listen")); // if address is in use already, just close the socket, but do not delete the file if(errno == EADDRINUSE) @@ -120,7 +121,7 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName) } // listen for connections - if (-1 == qListen(listenSocket, 50)) { + if (-1 == qt_safe_listen(listenSocket, 50)) { setError(QLatin1String("QLocalServer::listen")); closeServer(); listenSocket = -1; @@ -172,7 +173,7 @@ void QLocalServerPrivate::_q_onNewConnection() ::sockaddr_un addr; QT_SOCKLEN_T length = sizeof(sockaddr_un); - int connectedSocket = qAccept(listenSocket, (sockaddr *)&addr, &length); + int connectedSocket = qt_safe_accept(listenSocket, (sockaddr *)&addr, &length); if(-1 == connectedSocket) { setError(QLatin1String("QLocalSocket::activated")); closeServer(); diff --git a/src/network/socket/qlocalsocket_p.h b/src/network/socket/qlocalsocket_p.h index 24b5dd6..bdbba42 100644 --- a/src/network/socket/qlocalsocket_p.h +++ b/src/network/socket/qlocalsocket_p.h @@ -74,43 +74,6 @@ QT_BEGIN_NAMESPACE -#if !defined(Q_OS_WIN) && !defined(QT_LOCALSOCKET_TCP) -static inline int qSocket(int af, int socketype, int proto) -{ - int ret; - while((ret = qt_socket_socket(af, socketype, proto)) == -1 && errno == EINTR){} - return ret; -} - -static inline int qBind(int fd, const sockaddr *sa, int len) -{ - int ret; - while((ret = QT_SOCKET_BIND(fd, (sockaddr*)sa, len)) == -1 && errno == EINTR){} - return ret; -} - -static inline int qConnect(int fd, const sockaddr *sa, int len) -{ - int ret; - while((ret = QT_SOCKET_CONNECT(fd, (sockaddr*)sa, len)) == -1 && errno == EINTR){} - return ret; -} - -static inline int qListen(int fd, int backlog) -{ - int ret; - while((ret = qt_socket_listen(fd, backlog)) == -1 && errno == EINTR){} - return ret; -} - -static inline int qAccept(int fd, struct sockaddr *addr, QT_SOCKLEN_T *addrlen) -{ - int ret; - while((ret = qt_socket_accept(fd, addr, addrlen)) == -1 && errno == EINTR){} - return ret; -} -#endif //#if !defined(Q_OS_WIN) && !defined(QT_LOCALSOCKET_TCP) - #if !defined(Q_OS_WIN) || defined(QT_LOCALSOCKET_TCP) class QLocalUnixSocket : public QTcpSocket { diff --git a/src/network/socket/qlocalsocket_unix.cpp b/src/network/socket/qlocalsocket_unix.cpp index 41dac3c..d038794 100644 --- a/src/network/socket/qlocalsocket_unix.cpp +++ b/src/network/socket/qlocalsocket_unix.cpp @@ -41,6 +41,7 @@ #include "qlocalsocket.h" #include "qlocalsocket_p.h" +#include "qnet_unix_p.h" #ifndef QT_NO_LOCALSOCKET @@ -232,7 +233,7 @@ void QLocalSocket::connectToServer(const QString &name, OpenMode openMode) } // create the socket - if (-1 == (d->connectingSocket = qSocket(PF_UNIX, SOCK_STREAM, 0))) { + if (-1 == (d->connectingSocket = qt_safe_socket(PF_UNIX, SOCK_STREAM, 0))) { d->errorOccurred(UnsupportedSocketOperationError, QLatin1String("QLocalSocket::connectToServer")); return; @@ -282,7 +283,7 @@ void QLocalSocketPrivate::_q_connectToSocket() } ::memcpy(name.sun_path, connectingPathName.toLatin1().data(), connectingPathName.toLatin1().size() + 1); - if (-1 == qConnect(connectingSocket, (struct sockaddr *)&name, sizeof(name))) { + if (-1 == qt_safe_connect(connectingSocket, (struct sockaddr *)&name, sizeof(name))) { QString function = QLatin1String("QLocalSocket::connectToServer"); switch (errno) { diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp index 6eafe05..0c1fa19 100644 --- a/src/network/socket/qnativesocketengine_unix.cpp +++ b/src/network/socket/qnativesocketengine_unix.cpp @@ -42,7 +42,7 @@ //#define QNATIVESOCKETENGINE_DEBUG #include "qnativesocketengine_p.h" -#include "private/qcore_unix_p.h" +#include "private/qnet_unix_p.h" #include "qiodevice.h" #include "qhostaddress.h" #include "qvarlengtharray.h" @@ -162,7 +162,7 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc int protocol = AF_INET; #endif int type = (socketType == QAbstractSocket::UdpSocket) ? SOCK_DGRAM : SOCK_STREAM; - int socket = qt_socket_socket(protocol, type, 0); + int socket = qt_safe_socket(protocol, type, 0); if (socket <= 0) { switch (errno) { @@ -467,7 +467,7 @@ bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16 bool QNativeSocketEnginePrivate::nativeListen(int backlog) { - if (qt_socket_listen(socketDescriptor, backlog) < 0) { + if (qt_safe_listen(socketDescriptor, backlog) < 0) { switch (errno) { case EADDRINUSE: setError(QAbstractSocket::AddressInUseError, @@ -494,7 +494,7 @@ bool QNativeSocketEnginePrivate::nativeListen(int backlog) int QNativeSocketEnginePrivate::nativeAccept() { - int acceptedDescriptor = qt_socket_accept(socketDescriptor, 0, 0); + int acceptedDescriptor = qt_safe_accept(socketDescriptor, 0, 0); #if defined (QNATIVESOCKETENGINE_DEBUG) qDebug("QNativeSocketEnginePrivate::nativeAccept() == %i", acceptedDescriptor); #endif diff --git a/src/network/socket/qnet_unix_p.h b/src/network/socket/qnet_unix_p.h index 5256131..80a4c58 100644 --- a/src/network/socket/qnet_unix_p.h +++ b/src/network/socket/qnet_unix_p.h @@ -100,7 +100,7 @@ static inline int qt_safe_accept(int s, struct sockaddr *addr, QT_SOCKLEN_T *add Q_ASSERT((flags & ~O_NONBLOCK) == 0); register int fd; -#if 0 // no released version of glibc contains accept4 yet +#if QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC // use accept4 int sockflags = SOCK_CLOEXEC; if (flags & O_NONBLOCK) -- cgit v0.12 From a32019f4c2f56a84172bde739d7ea174be0db381 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 25 Jun 2009 17:22:53 +0200 Subject: Add qobject_cast for QSharedPointer. This obviously only works for classes that derive from QObject. And you must remember that QSharedPointer controls the QObject's lifetime, not the QObject parent-child relationship. Reviewed-by: dt Reviewed-by: Bradley T. Hughes --- src/corelib/tools/qsharedpointer.cpp | 56 +++++++++++ src/corelib/tools/qsharedpointer.h | 3 + src/corelib/tools/qsharedpointer_impl.h | 51 ++++++++++ tests/auto/qsharedpointer/tst_qsharedpointer.cpp | 123 +++++++++++++++++++++++ 4 files changed, 233 insertions(+) diff --git a/src/corelib/tools/qsharedpointer.cpp b/src/corelib/tools/qsharedpointer.cpp index ba62ce1..71bf318 100644 --- a/src/corelib/tools/qsharedpointer.cpp +++ b/src/corelib/tools/qsharedpointer.cpp @@ -340,6 +340,23 @@ */ /*! + \fn QSharedPointer QSharedPointer::objectCast() const + + Performs a \ref qobject_cast from this pointer's type to \tt X and + returns a QSharedPointer that shares the reference. If this + function is used to up-cast, then QSharedPointer will perform a \tt + qobject_cast, which means that if the object being pointed by this + QSharedPointer is not of type \tt X, the returned object will be + null. + + Note: the template type \c X must have the same const and volatile + qualifiers as the template of this object, or the cast will + fail. Use constCast() if you need to drop those qualifiers. + + \sa qSharedPointerObjectCast() +*/ + +/*! \fn QWeakPointer QSharedPointer::toWeakRef() const Returns a weak reference object that shares the pointer referenced @@ -718,6 +735,45 @@ */ /*! + \fn QSharedPointer qSharedPointerObjectCast(const QSharedPointer &other) + \relates QSharedPointer + + Returns a shared pointer to the pointer held by \a other, using a + \ref qobject_cast to type \tt X to obtain an internal pointer of the + appropriate type. If the \tt qobject_cast fails, the object + returned will be null. + + Note that \tt X must have the same cv-qualifiers (\tt const and + \tt volatile) that \tt T has, or the code will fail to + compile. Use qSharedPointerConstCast to cast away the constness. + + \sa QSharedPointer::objectCast(), qSharedPointerCast(), qSharedPointerConstCast() +*/ + +/*! + \fn QSharedPointer qSharedPointerObjectCast(const QWeakPointer &other) + \relates QSharedPointer + \relates QWeakPointer + + Returns a shared pointer to the pointer held by \a other, using a + \ref qobject_cast to type \tt X to obtain an internal pointer of the + appropriate type. If the \tt qobject_cast fails, the object + returned will be null. + + The \a other object is converted first to a strong reference. If + that conversion fails (because the object it's pointing to has + already been deleted), this function also returns a null + QSharedPointer. + + Note that \tt X must have the same cv-qualifiers (\tt const and + \tt volatile) that \tt T has, or the code will fail to + compile. Use qSharedPointerConstCast to cast away the constness. + + \sa QWeakPointer::toStrongRef(), qSharedPointerCast(), qSharedPointerConstCast() +*/ + + +/*! \fn QWeakPointer qWeakPointerCast(const QWeakPointer &other) \relates QWeakPointer diff --git a/src/corelib/tools/qsharedpointer.h b/src/corelib/tools/qsharedpointer.h index cd6bc62..abd83ad 100644 --- a/src/corelib/tools/qsharedpointer.h +++ b/src/corelib/tools/qsharedpointer.h @@ -93,6 +93,7 @@ public: template QSharedPointer staticCast() const; template QSharedPointer dynamicCast() const; template QSharedPointer constCast() const; + template QSharedPointer objectCast() const; }; template @@ -136,6 +137,8 @@ template QSharedPointer qSharedPointerDynamicCast(const QS template QSharedPointer qSharedPointerDynamicCast(const QWeakPointer &src); template QSharedPointer qSharedPointerConstCast(const QSharedPointer &src); template QSharedPointer qSharedPointerConstCast(const QWeakPointer &src); +template QSharedPointer qSharedPointerObjectCast(const QSharedPointer &src); +template QSharedPointer qSharedPointerObjectCast(const QWeakPointer &src); template QWeakPointer qWeakPointerCast(const QWeakPointer &src); diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h index 2797622..df31fec 100644 --- a/src/corelib/tools/qsharedpointer_impl.h +++ b/src/corelib/tools/qsharedpointer_impl.h @@ -49,6 +49,7 @@ #endif #include +#include // for qobject_cast QT_BEGIN_HEADER @@ -83,6 +84,11 @@ QSharedPointer qSharedPointerDynamicCast(const QSharedPointer &ptr); template QSharedPointer qSharedPointerConstCast(const QSharedPointer &ptr); +#ifndef QT_NO_QOBJECT +template +QSharedPointer qSharedPointerObjectCast(const QSharedPointer &ptr); +#endif + namespace QtSharedPointer { template class InternalRefCount; template class ExternalRefCount; @@ -330,6 +336,14 @@ public: return qSharedPointerConstCast(*this); } +#ifndef QT_NO_QOBJECT + template + QSharedPointer objectCast() const + { + return qSharedPointerObjectCast(*this); + } +#endif + inline void clear() { *this = QSharedPointer(); } QWeakPointer toWeakRef() const; @@ -545,6 +559,43 @@ QWeakPointer qWeakPointerCast(const QSharedPointer &src) return qSharedPointerCast(src).toWeakRef(); } +#ifndef QT_NO_QOBJECT +template +Q_INLINE_TEMPLATE QSharedPointer qSharedPointerObjectCast(const QSharedPointer &src) +{ + register X *ptr = qobject_cast(src.data()); + return QtSharedPointer::copyAndSetPointer(ptr, src); +} +template +Q_INLINE_TEMPLATE QSharedPointer qSharedPointerObjectCast(const QWeakPointer &src) +{ + return qSharedPointerObjectCast(src.toStrongRef()); +} + +# ifndef QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION +namespace QtSharedPointer { + template struct RemovePointer; + template struct RemovePointer { typedef T Type; }; + template struct RemovePointer > { typedef T Type; }; + template struct RemovePointer > { typedef T Type; }; +} + +template +inline QSharedPointer::Type> +qobject_cast(const QSharedPointer &src) +{ + return qSharedPointerObjectCast::Type, T>(src); +} +template +inline QSharedPointer::Type> +qobject_cast(const QWeakPointer &src) +{ + return qSharedPointerObjectCast::Type, T>(src); +} +# endif + +#endif + QT_END_NAMESPACE QT_END_HEADER diff --git a/tests/auto/qsharedpointer/tst_qsharedpointer.cpp b/tests/auto/qsharedpointer/tst_qsharedpointer.cpp index db93fc9..57ebdce 100644 --- a/tests/auto/qsharedpointer/tst_qsharedpointer.cpp +++ b/tests/auto/qsharedpointer/tst_qsharedpointer.cpp @@ -56,6 +56,7 @@ private slots: void memoryManagement(); void downCast(); void upCast(); + void objectCast(); void differentPointers(); void virtualBaseDifferentPointers(); #ifndef QTEST_NO_RTTI @@ -424,6 +425,109 @@ void tst_QSharedPointer::upCast() QCOMPARE(int(baseptr.d->strongref), 1); } +class OtherObject: public QObject +{ + Q_OBJECT +}; + +void tst_QSharedPointer::objectCast() +{ + { + OtherObject *data = new OtherObject; + QSharedPointer baseptr = QSharedPointer(data); + QVERIFY(baseptr == data); + QVERIFY(data == baseptr); + + // perform object cast + QSharedPointer ptr = qSharedPointerObjectCast(baseptr); + QVERIFY(!ptr.isNull()); + QCOMPARE(ptr.data(), data); + QVERIFY(ptr == data); + + // again: + ptr = baseptr.objectCast(); + QVERIFY(ptr == data); + +#ifndef QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION + // again: + ptr = qobject_cast(baseptr); + QVERIFY(ptr == data); + + // again: + ptr = qobject_cast >(baseptr); + QVERIFY(ptr == data); +#endif + } + + { + const OtherObject *data = new OtherObject; + QSharedPointer baseptr = QSharedPointer(data); + QVERIFY(baseptr == data); + QVERIFY(data == baseptr); + + // perform object cast + QSharedPointer ptr = qSharedPointerObjectCast(baseptr); + QVERIFY(!ptr.isNull()); + QCOMPARE(ptr.data(), data); + QVERIFY(ptr == data); + + // again: + ptr = baseptr.objectCast(); + QVERIFY(ptr == data); + +#ifndef QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION + // again: + ptr = qobject_cast(baseptr); + QVERIFY(ptr == data); + + // again: + ptr = qobject_cast >(baseptr); + QVERIFY(ptr == data); +#endif + } + + { + OtherObject *data = new OtherObject; + QPointer qptr = data; + QSharedPointer ptr = QSharedPointer(data); + QWeakPointer weakptr = ptr; + + { + // perform object cast + QSharedPointer otherptr = qSharedPointerObjectCast(weakptr); + QVERIFY(otherptr == ptr); + + // again: + otherptr = qobject_cast(weakptr); + QVERIFY(otherptr == ptr); + + // again: + otherptr = qobject_cast >(weakptr); + QVERIFY(otherptr == ptr); + } + + // drop the reference: + ptr.clear(); + QVERIFY(ptr.isNull()); + QVERIFY(qptr.isNull()); + QVERIFY(weakptr.toStrongRef().isNull()); + + // verify that the object casts fail without crash + QSharedPointer otherptr = qSharedPointerObjectCast(weakptr); + QVERIFY(otherptr.isNull()); + +#ifndef QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION + // again: + otherptr = qobject_cast(weakptr); + QVERIFY(otherptr.isNull()); + + // again: + otherptr = qobject_cast >(weakptr); + QVERIFY(otherptr.isNull()); +#endif + } +} + void tst_QSharedPointer::differentPointers() { { @@ -939,6 +1043,20 @@ void tst_QSharedPointer::invalidConstructs_data() << "QSharedPointer baseptr = QSharedPointer(new Data);\n" "QSharedPointer ptr;" "ptr = baseptr;"; + QTest::newRow("const-dropping-static-cast") + << &QTest::QExternalTest::tryCompileFail + << "QSharedPointer baseptr = QSharedPointer(new Data);\n" + "qSharedPointerCast(baseptr);"; +#ifndef QTEST_NO_RTTI + QTest::newRow("const-dropping-dynamic-cast") + << &QTest::QExternalTest::tryCompileFail + << "QSharedPointer baseptr = QSharedPointer(new Data);\n" + "qSharedPointerDynamicCast(baseptr);"; +#endif + QTest::newRow("const-dropping-object-cast") + << &QTest::QExternalTest::tryCompileFail + << "QSharedPointer baseptr = QSharedPointer(new QObject);\n" + "qSharedPointerObjectCast(baseptr);"; // arithmethics through automatic cast operators QTest::newRow("arithmethic1") @@ -982,6 +1100,10 @@ void tst_QSharedPointer::invalidConstructs_data() << &QTest::QExternalTest::tryCompileFail << "QSharedPointer ptr1;\n" "QSharedPointer ptr2 = qSharedPointerConstCast(ptr1);"; + QTest::newRow("invalid-cast4") + << &QTest::QExternalTest::tryCompileFail + << "QSharedPointer ptr1;\n" + "QSharedPointer ptr2 = qSharedPointerObjectCast(ptr1);"; } void tst_QSharedPointer::invalidConstructs() @@ -999,6 +1121,7 @@ void tst_QSharedPointer::invalidConstructs() test.setProgramHeader( "#define QT_SHAREDPOINTER_TRACK_POINTERS\n" "#include \n" + "#include \n" "\n" "struct Data { int i; };\n" "struct DerivedData: public Data { int j; };\n" -- cgit v0.12 From fb51a10ee0451274a430227566ae26efb2ac4474 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 25 Jun 2009 20:52:36 +0200 Subject: Add support for creating the object alongside the Data structure in one go. This avoids one memory allocation. Currently, we only support calling the default constructors. I will *NOT* implement argument passing for C++03. I will implement it with rvalue references for C++0x-capable compilers. --- src/corelib/tools/qsharedpointer_impl.h | 47 +++++++++++ tests/auto/qsharedpointer/tst_qsharedpointer.cpp | 102 ++++++++++++++++++++++- 2 files changed, 147 insertions(+), 2 deletions(-) diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h index df31fec..cb78f29 100644 --- a/src/corelib/tools/qsharedpointer_impl.h +++ b/src/corelib/tools/qsharedpointer_impl.h @@ -48,6 +48,7 @@ #pragma qt_sync_stop_processing #endif +#include #include #include // for qobject_cast @@ -190,6 +191,34 @@ namespace QtSharedPointer { }; template + struct ExternalRefCountWithContiguousData: public ExternalRefCountData + { +#ifdef Q_DECL_ALIGN +# ifdef Q_ALIGNOF +# define QSP_ALIGNOF(T) Q_ALIGNOF(T) +# else +# define QSP_ALIGNOF(T) (sizeof(T) >= 16 ? 16 : sizeof(T) >= 8 ? 8 : sizeof(T) >= 4 ? 4 : sizeof(T) >= 2 ? 2 : 1) +# endif + + char data[sizeof(T)] Q_DECL_ALIGN(QSP_ALIGNOF(T)); + inline T *pointer() { return reinterpret_cast(data); } + +# undef QSP_ALIGNOF +#else + union { + char data[sizeof(T) + 16]; + double dummy1; +# ifndef Q_OS_DARWIN + long double dummy2; +# endif + }; + inline T *pointer() { return reinterpret_cast(data + 16 - (quintptr(data) & 0xf)); } +#endif + + inline bool destroy() { this->pointer()->~T(); return true; } + }; + + template class ExternalRefCount: public Basic { typedef ExternalRefCountData Data; @@ -220,6 +249,16 @@ namespace QtSharedPointer { d = new ExternalRefCountWithSpecializedDeleter(ptr, deleter); } + inline void internalCreate() + { + ExternalRefCountWithContiguousData *dd = new ExternalRefCountWithContiguousData; + T *ptr = dd->pointer(); + new (ptr) T(); // create + + Basic::internalConstruct(ptr); + d = dd; + } + inline ExternalRefCount() : d(0) { } inline ~ExternalRefCount() { if (d && !deref()) delete d; } inline ExternalRefCount(const ExternalRefCount &other) : Basic(other), d(other.d) @@ -347,6 +386,14 @@ public: inline void clear() { *this = QSharedPointer(); } QWeakPointer toWeakRef() const; + +public: + static QSharedPointer create() + { + QSharedPointer result; + result.internalCreate(); + return result; + } }; template diff --git a/tests/auto/qsharedpointer/tst_qsharedpointer.cpp b/tests/auto/qsharedpointer/tst_qsharedpointer.cpp index 57ebdce..d6321c7 100644 --- a/tests/auto/qsharedpointer/tst_qsharedpointer.cpp +++ b/tests/auto/qsharedpointer/tst_qsharedpointer.cpp @@ -65,8 +65,9 @@ private slots: void dynamicCastVirtualBase(); void dynamicCastFailure(); #endif - void customDeleter(); void constCorrectness(); + void customDeleter(); + void creating(); void validConstructs(); void invalidConstructs_data(); void invalidConstructs(); @@ -104,6 +105,8 @@ public: { delete this; } + + virtual int classLevel() { return 1; } }; int Data::generationCounter = 0; int Data::destructorCounter = 0; @@ -311,6 +314,8 @@ public: { delete this; } + + virtual int classLevel() { return 2; } }; int DerivedData::derivedDestructorCounter = 0; @@ -318,15 +323,23 @@ class Stuffing { public: char buffer[16]; + Stuffing() { for (uint i = 0; i < sizeof buffer; ++i) buffer[i] = 16 - i; } virtual ~Stuffing() { } }; class DiffPtrDerivedData: public Stuffing, public Data { +public: + virtual int classLevel() { return 3; } }; class VirtualDerived: virtual public Data { +public: + int moreData; + + VirtualDerived() : moreData(0xc0ffee) { } + virtual int classLevel() { return 4; } }; void tst_QSharedPointer::downCast() @@ -972,6 +985,82 @@ void tst_QSharedPointer::customDeleter() QCOMPARE(derivedDataDeleter.callCount, 1); } +void tst_QSharedPointer::creating() +{ + Data::generationCounter = Data::destructorCounter = 0; + { + QSharedPointer ptr = QSharedPointer::create(); + QVERIFY(ptr.data()); + QCOMPARE(Data::generationCounter, 1); + QCOMPARE(ptr->generation, 1); + QCOMPARE(Data::destructorCounter, 0); + + QCOMPARE(ptr->classLevel(), 1); + + ptr.clear(); + QCOMPARE(Data::destructorCounter, 1); + } + + Data::generationCounter = Data::destructorCounter = 0; + { + QSharedPointer ptr = QSharedPointer::create(); + QWeakPointer weakptr = ptr; + QtSharedPointer::ExternalRefCountData *d = ptr.d; + + ptr.clear(); + QVERIFY(ptr.isNull()); + QCOMPARE(Data::destructorCounter, 1); + + // valgrind will complain here if something happened to the pointer + QVERIFY(d->weakref == 1); + QVERIFY(d->strongref == 0); + } + + Data::generationCounter = Data::destructorCounter = 0; + DerivedData::derivedDestructorCounter = 0; + { + QSharedPointer ptr = QSharedPointer::create(); + QCOMPARE(ptr->classLevel(), 2); + QCOMPARE(ptr.staticCast()->moreData, 0); + ptr.clear(); + + QCOMPARE(Data::destructorCounter, 1); + QCOMPARE(DerivedData::derivedDestructorCounter, 1); + } + + { + QSharedPointer ptr = QSharedPointer::create(); + QCOMPARE(ptr->classLevel(), 3); + QCOMPARE(ptr.staticCast()->buffer[7]+0, 16-7); + QCOMPARE(ptr.staticCast()->buffer[3]+0, 16-3); + QCOMPARE(ptr.staticCast()->buffer[0]+0, 16); + } + + { + QSharedPointer ptr = QSharedPointer::create(); + QCOMPARE(ptr->classLevel(), 4); + QCOMPARE(ptr->moreData, 0xc0ffee); + + QSharedPointer baseptr = ptr; + QCOMPARE(baseptr->classLevel(), 4); + } + + { + QSharedPointer ptr = QSharedPointer::create(); + QCOMPARE(ptr->metaObject(), &QObject::staticMetaObject); + + QPointer qptr = ptr.data(); + ptr.clear(); + + QVERIFY(qptr.isNull()); + } + + { + QSharedPointer ptr = QSharedPointer::create(); + QCOMPARE(ptr->metaObject(), &OtherObject::staticMetaObject); + } +} + void tst_QSharedPointer::validConstructs() { { @@ -1021,6 +1110,9 @@ void tst_QSharedPointer::invalidConstructs_data() QTest::newRow("forward-declaration") << &QTest::QExternalTest::tryCompileFail << "QSharedPointer ptr;"; + QTest::newRow("creating-forward-declaration") + << &QTest::QExternalTest::tryCompileFail + << "QSharedPointer::create();"; // upcast without cast operator: QTest::newRow("upcast1") @@ -1053,10 +1145,16 @@ void tst_QSharedPointer::invalidConstructs_data() << "QSharedPointer baseptr = QSharedPointer(new Data);\n" "qSharedPointerDynamicCast(baseptr);"; #endif - QTest::newRow("const-dropping-object-cast") + QTest::newRow("const-dropping-object-cast1") << &QTest::QExternalTest::tryCompileFail << "QSharedPointer baseptr = QSharedPointer(new QObject);\n" "qSharedPointerObjectCast(baseptr);"; +#ifndef QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION + QTest::newRow("const-dropping-object-cast2") + << &QTest::QExternalTest::tryCompileFail + << "QSharedPointer baseptr = QSharedPointer(new QObject);\n" + "qobject_cast(baseptr);"; +#endif // arithmethics through automatic cast operators QTest::newRow("arithmethic1") -- cgit v0.12 From 6f673e2cf55755a97aeb8971994ab9fc62fb794e Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 25 Jun 2009 21:01:24 +0200 Subject: Experimental: allow QSharedPointer to be used with forward declarations that are declared in this file. The one-definition rule allows the forward declaration appearing below to apply to code that was earlier. Therefore, if the compiler finds out how to delete the object, we can allow a QSharedPointer of a forward- declared-type. This means the actual problem is just a warning with g++. To catch the error, we need a separate .cpp file and I'd rather run this as an external test. --- src/corelib/tools/qsharedpointer_impl.h | 2 +- tests/auto/qsharedpointer/externaltests.cpp | 20 ++++++++- tests/auto/qsharedpointer/externaltests.h | 4 ++ tests/auto/qsharedpointer/externaltests.pri | 1 + tests/auto/qsharedpointer/forwarddeclaration.cpp | 52 +++++++++++++++++++++++ tests/auto/qsharedpointer/forwarddeclared.cpp | 53 +++++++++++++++++++++++ tests/auto/qsharedpointer/forwarddeclared.h | 54 ++++++++++++++++++++++++ tests/auto/qsharedpointer/qsharedpointer.pro | 9 ++-- tests/auto/qsharedpointer/tst_qsharedpointer.cpp | 42 +++++++++++++++--- 9 files changed, 224 insertions(+), 13 deletions(-) create mode 100644 tests/auto/qsharedpointer/forwarddeclaration.cpp create mode 100644 tests/auto/qsharedpointer/forwarddeclared.cpp create mode 100644 tests/auto/qsharedpointer/forwarddeclared.h diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h index cb78f29..2fa9eb2 100644 --- a/src/corelib/tools/qsharedpointer_impl.h +++ b/src/corelib/tools/qsharedpointer_impl.h @@ -129,7 +129,7 @@ namespace QtSharedPointer { inline T *operator->() const { return data(); } protected: - inline Basic() : value(0 * sizeof(T)) { } + inline Basic() : value(0) { } // ~Basic(); inline void verifyReconstruction(const T *ptr) diff --git a/tests/auto/qsharedpointer/externaltests.cpp b/tests/auto/qsharedpointer/externaltests.cpp index 75ac5f1..8077b84 100644 --- a/tests/auto/qsharedpointer/externaltests.cpp +++ b/tests/auto/qsharedpointer/externaltests.cpp @@ -59,7 +59,7 @@ static QString makespec() { static const char default_makespec[] = DEFAULT_MAKESPEC; const char *p; - for (p = default_makespec + sizeof(default_makespec); p >= default_makespec; --p) + for (p = default_makespec + sizeof(default_makespec) - 1; p >= default_makespec; --p) if (*p == '/' || *p == '\\') break; @@ -122,6 +122,7 @@ namespace QTest { enum Target { Compile, Link, Run }; QList qmakeLines; + QStringList extraProgramSources; QByteArray programHeader; QExternalTest::QtModules qtModules; QExternalTest::ApplicationType appType; @@ -199,6 +200,16 @@ namespace QTest { d->appType = type; } + QStringList QExternalTest::extraProgramSources() const + { + return d->extraProgramSources; + } + + void QExternalTest::setExtraProgramSources(const QStringList &extra) + { + d->extraProgramSources = extra; + } + QByteArray QExternalTest::programHeader() const { return d->programHeader; @@ -483,6 +494,13 @@ namespace QTest { else projectFile.write("\nCONFIG += release\n"); + QByteArray extraSources = QFile::encodeName(extraProgramSources.join(" ")); + if (!extraSources.isEmpty()) { + projectFile.write("SOURCES += "); + projectFile.write(extraSources); + projectFile.putChar('\n'); + } + // Add Qt modules if (qtModules & QExternalTest::QtCore) projectFile.write("QT += core\n"); diff --git a/tests/auto/qsharedpointer/externaltests.h b/tests/auto/qsharedpointer/externaltests.h index 24a3236..ecc107e 100644 --- a/tests/auto/qsharedpointer/externaltests.h +++ b/tests/auto/qsharedpointer/externaltests.h @@ -45,6 +45,7 @@ #include #include +#include QT_BEGIN_NAMESPACE namespace QTest { @@ -102,6 +103,9 @@ namespace QTest { ApplicationType applicationType() const; void setApplicationType(ApplicationType type); + QStringList extraProgramSources() const; + void setExtraProgramSources(const QStringList &list); + QByteArray programHeader() const; void setProgramHeader(const QByteArray &header); diff --git a/tests/auto/qsharedpointer/externaltests.pri b/tests/auto/qsharedpointer/externaltests.pri index 717acac..1fdcf65 100644 --- a/tests/auto/qsharedpointer/externaltests.pri +++ b/tests/auto/qsharedpointer/externaltests.pri @@ -1,4 +1,5 @@ SOURCES += $$PWD/externaltests.cpp +HEADERS += $$PWD/externaltests.h cleanedQMAKESPEC = $$replace(QMAKESPEC, \\\\, /) DEFINES += DEFAULT_MAKESPEC=\\\"$$cleanedQMAKESPEC\\\" diff --git a/tests/auto/qsharedpointer/forwarddeclaration.cpp b/tests/auto/qsharedpointer/forwarddeclaration.cpp new file mode 100644 index 0000000..1dbbeec --- /dev/null +++ b/tests/auto/qsharedpointer/forwarddeclaration.cpp @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#define QT_SHAREDPOINTER_TRACK_POINTERS +#include "qsharedpointer.h" + +class ForwardDeclared; +ForwardDeclared *forwardPointer(); + +void externalForwardDeclaration() +{ + struct Wrapper { QSharedPointer pointer; }; +} + diff --git a/tests/auto/qsharedpointer/forwarddeclared.cpp b/tests/auto/qsharedpointer/forwarddeclared.cpp new file mode 100644 index 0000000..4ab467a --- /dev/null +++ b/tests/auto/qsharedpointer/forwarddeclared.cpp @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "forwarddeclared.h" + +ForwardDeclared *forwardPointer() +{ + return new ForwardDeclared; +} + +int forwardDeclaredDestructorRunCount; +ForwardDeclared::~ForwardDeclared() +{ + ++forwardDeclaredDestructorRunCount; +} diff --git a/tests/auto/qsharedpointer/forwarddeclared.h b/tests/auto/qsharedpointer/forwarddeclared.h new file mode 100644 index 0000000..a4cc2b4 --- /dev/null +++ b/tests/auto/qsharedpointer/forwarddeclared.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef FORWARDDECLARED_H +#define FORWARDDECLARED_H + +extern int forwardDeclaredDestructorRunCount; +class ForwardDeclared +{ +public: + ~ForwardDeclared(); +}; + +ForwardDeclared *forwardPointer(); + +#endif // FORWARDDECLARED_H diff --git a/tests/auto/qsharedpointer/qsharedpointer.pro b/tests/auto/qsharedpointer/qsharedpointer.pro index e329803..30c81cb 100644 --- a/tests/auto/qsharedpointer/qsharedpointer.pro +++ b/tests/auto/qsharedpointer/qsharedpointer.pro @@ -1,7 +1,8 @@ load(qttest_p4) - -SOURCES += tst_qsharedpointer.cpp +SOURCES += tst_qsharedpointer.cpp \ + forwarddeclaration.cpp \ + forwarddeclared.cpp QT = core -DEFINES += SRCDIR=\\\"$$PWD\\\" - +DEFINES += SRCDIR=\\\"$$PWD/\\\" include(externaltests.pri) +HEADERS += forwarddeclared.h diff --git a/tests/auto/qsharedpointer/tst_qsharedpointer.cpp b/tests/auto/qsharedpointer/tst_qsharedpointer.cpp index d6321c7..dd53e3c 100644 --- a/tests/auto/qsharedpointer/tst_qsharedpointer.cpp +++ b/tests/auto/qsharedpointer/tst_qsharedpointer.cpp @@ -225,16 +225,37 @@ void tst_QSharedPointer::basics() } class ForwardDeclared; +ForwardDeclared *forwardPointer(); +void externalForwardDeclaration(); +extern int forwardDeclaredDestructorRunCount; + void tst_QSharedPointer::forwardDeclaration1() { - class Wrapper { QSharedPointer pointer; }; + externalForwardDeclaration(); + + struct Wrapper { QSharedPointer pointer; }; + + forwardDeclaredDestructorRunCount = 0; + { + Wrapper w; + w.pointer = QSharedPointer(forwardPointer()); + QVERIFY(!w.pointer.isNull()); + } + QCOMPARE(forwardDeclaredDestructorRunCount, 1); } -class ForwardDeclared { }; +#include "forwarddeclared.h" + void tst_QSharedPointer::forwardDeclaration2() { - class Wrapper { QSharedPointer pointer; }; - Wrapper w; + forwardDeclaredDestructorRunCount = 0; + { + struct Wrapper { QSharedPointer pointer; }; + Wrapper w1, w2; + w1.pointer = QSharedPointer(forwardPointer()); + QVERIFY(!w1.pointer.isNull()); + } + QCOMPARE(forwardDeclaredDestructorRunCount, 1); } void tst_QSharedPointer::memoryManagement() @@ -1108,8 +1129,10 @@ void tst_QSharedPointer::invalidConstructs_data() // use of forward-declared class QTest::newRow("forward-declaration") - << &QTest::QExternalTest::tryCompileFail - << "QSharedPointer ptr;"; + << &QTest::QExternalTest::tryRun + << "forwardDeclaredDestructorRunCount = 0;\n" + "{ QSharedPointer ptr = QSharedPointer(forwardPointer()); }\n" + "exit(forwardDeclaredDestructorRunCount);"; QTest::newRow("creating-forward-declaration") << &QTest::QExternalTest::tryCompileFail << "QSharedPointer::create();"; @@ -1216,6 +1239,7 @@ void tst_QSharedPointer::invalidConstructs() QTest::QExternalTest test; test.setDebugMode(true); test.setQtModules(QTest::QExternalTest::QtCore); + test.setExtraProgramSources(QStringList() << SRCDIR "forwarddeclared.cpp"); test.setProgramHeader( "#define QT_SHAREDPOINTER_TRACK_POINTERS\n" "#include \n" @@ -1223,7 +1247,11 @@ void tst_QSharedPointer::invalidConstructs() "\n" "struct Data { int i; };\n" "struct DerivedData: public Data { int j; };\n" - "struct ForwardDeclared;"); + "\n" + "extern int forwardDeclaredDestructorRunCount;\n" + "struct ForwardDeclared;\n" + "ForwardDeclared *forwardPointer();\n" + ); QFETCH(QString, code); static bool sane = true; -- cgit v0.12 From d70839d4fd855d6d5f6bf8d982b677402f71e5ba Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 2 Jul 2009 14:14:51 +0200 Subject: These files don't have to have CRLF line-termination. The other files here don't, so I see no reason why these should --- examples/tools/codecs/encodedfiles/.gitattributes | 2 -- examples/tools/codecs/encodedfiles/iso-8859-1.txt | 12 ++++++------ examples/tools/codecs/encodedfiles/iso-8859-15.txt | 16 ++++++++-------- 3 files changed, 14 insertions(+), 16 deletions(-) delete mode 100644 examples/tools/codecs/encodedfiles/.gitattributes diff --git a/examples/tools/codecs/encodedfiles/.gitattributes b/examples/tools/codecs/encodedfiles/.gitattributes deleted file mode 100644 index 996aab2..0000000 --- a/examples/tools/codecs/encodedfiles/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -iso-8859-15.txt -crlf -iso-8859-1.txt -crlf diff --git a/examples/tools/codecs/encodedfiles/iso-8859-1.txt b/examples/tools/codecs/encodedfiles/iso-8859-1.txt index 4a7ebe3..d7fcaca 100644 --- a/examples/tools/codecs/encodedfiles/iso-8859-1.txt +++ b/examples/tools/codecs/encodedfiles/iso-8859-1.txt @@ -1,6 +1,6 @@ -Paulo Coelho: O Gênio e as Rosas -Anna Hallström, Urban Östberg: Svår svenska -Darrell Huff: How to Lie with Statistics -Franz Kafka: Das Schloß -Walter Moers: Die 13½ Leben des Käpt'n Blaubär -Dag Solstad: Forsøk på å beskrive det ugjennomtrengelige +Paulo Coelho: O Gênio e as Rosas +Anna Hallström, Urban Östberg: Svår svenska +Darrell Huff: How to Lie with Statistics +Franz Kafka: Das Schloß +Walter Moers: Die 13½ Leben des Käpt'n Blaubär +Dag Solstad: Forsøk på å beskrive det ugjennomtrengelige diff --git a/examples/tools/codecs/encodedfiles/iso-8859-15.txt b/examples/tools/codecs/encodedfiles/iso-8859-15.txt index cd43ea3..be2d83c 100644 --- a/examples/tools/codecs/encodedfiles/iso-8859-15.txt +++ b/examples/tools/codecs/encodedfiles/iso-8859-15.txt @@ -1,8 +1,8 @@ -Paulo Coelho: O Gênio e as Rosas -Jean-Pierre Coffe: À table en famille avec 15 ¤ par jour -Anna Hallström, Urban Östberg: Svår svenska -Darrell Huff: How to Lie with Statistics -Franz Kafka: Das Schloß -Helena Lehecková: T¨ekkiä suomalaisille -Arthur Rimbaud: ¼uvres complètes -Dag Solstad: Forsøk på å beskrive det ugjennomtrengelige +Paulo Coelho: O Gênio e as Rosas +Jean-Pierre Coffe: À table en famille avec 15 ¤ par jour +Anna Hallström, Urban Östberg: Svår svenska +Darrell Huff: How to Lie with Statistics +Franz Kafka: Das Schloß +Helena Lehecková: T¨ekkiä suomalaisille +Arthur Rimbaud: ¼uvres complètes +Dag Solstad: Forsøk på å beskrive det ugjennomtrengelige -- cgit v0.12 From c4ae87721e011fe44f301c4039f0651a05394162 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 2 Jul 2009 14:59:51 +0200 Subject: Speedup item-lookup in Graphics View. We don't have to do a stable sort anymore because the lessThan operator now accounts for the insertion order. This also means we don't have to sort all top-level items to preserve the insertion order in QGraphicsScenePrivate::topLevelItemsInStackingOrder. Reviewed-by: Andreas --- src/gui/graphicsview/qgraphicsitem.cpp | 5 +++ src/gui/graphicsview/qgraphicsitem_p.h | 17 +++++++ src/gui/graphicsview/qgraphicsscene.cpp | 52 ++++++++++------------ src/gui/graphicsview/qgraphicsscene_p.h | 8 ++++ .../graphicsview/qgraphicsscenebsptreeindex.cpp | 12 ++--- .../graphicsview/qgraphicsscenebsptreeindex_p.h | 18 +++----- src/gui/graphicsview/qgraphicssceneindex.cpp | 5 +-- 7 files changed, 65 insertions(+), 52 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 002eab9..9a27ef5 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -4310,6 +4310,7 @@ void QGraphicsItemPrivate::resolveDepth(int parentDepth) void QGraphicsItemPrivate::addChild(QGraphicsItem *child) { needSortChildren = 1; + child->d_ptr->siblingIndex = children.size(); children.append(child); } @@ -4319,6 +4320,10 @@ void QGraphicsItemPrivate::addChild(QGraphicsItem *child) void QGraphicsItemPrivate::removeChild(QGraphicsItem *child) { children.removeOne(child); + // NB! Do not use children.removeAt(child->d_ptr->siblingIndex) because + // the child is not guaranteed to be at the index after the list is sorted. + // (see ensureSortedChildren()). + child->d_ptr->siblingIndex = -1; } /*! diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index a4b2c25..99865b0 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -126,6 +126,7 @@ public: parent(0), transformData(0), index(-1), + siblingIndex(-1), depth(0), acceptedMouseButtons(0x1f), visible(1), @@ -386,6 +387,7 @@ public: } inline QTransform transformToParent() const; + inline void ensureSortedChildren(); QPainterPath cachedClipPath; QRectF childrenBoundingRect; @@ -401,6 +403,7 @@ public: TransformData *transformData; QTransform sceneTransform; int index; + int siblingIndex; int depth; inline QGestureExtraData* extraGestures() const @@ -517,6 +520,12 @@ struct QGraphicsItemPrivate::TransformData { } }; +/*! + \internal +*/ +static inline bool qt_notclosestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2) +{ return qt_closestLeaf(item2, item1); } + /* return the full transform of the item to the parent. This include the position and all the transform data */ @@ -527,6 +536,14 @@ inline QTransform QGraphicsItemPrivate::transformToParent() const return matrix; } +inline void QGraphicsItemPrivate::ensureSortedChildren() +{ + if (needSortChildren) { + qSort(children.begin(), children.end(), qt_notclosestLeaf); + needSortChildren = 0; + } +} + QT_END_NAMESPACE #endif // QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 8a032f4..3b1c8ad 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -375,6 +375,7 @@ void QGraphicsScenePrivate::_q_emitUpdated() void QGraphicsScenePrivate::registerTopLevelItem(QGraphicsItem *item) { needSortTopLevelItems = true; + item->d_ptr->siblingIndex = topLevelItems.size(); topLevelItems.append(item); } @@ -384,6 +385,10 @@ void QGraphicsScenePrivate::registerTopLevelItem(QGraphicsItem *item) void QGraphicsScenePrivate::unregisterTopLevelItem(QGraphicsItem *item) { topLevelItems.removeOne(item); + // NB! Do not use topLevelItems.removeAt(item->d_ptr->siblingIndex) because + // the item is not guaranteed to be at the index after the list is sorted + // (see ensureSortedTopLevelItems()). + item->d_ptr->siblingIndex = -1; } /*! @@ -1084,37 +1089,29 @@ QList QGraphicsScenePrivate::topLevelItemsInStackingOrder(const const QRectF &sceneRect) { if (indexMethod == QGraphicsScene::NoIndex || sceneRect.isNull()) { - if (needSortTopLevelItems) { - needSortTopLevelItems = false; - qStableSort(topLevelItems.begin(), topLevelItems.end(), qt_notclosestLeaf); - } + ensureSortedTopLevelItems(); return topLevelItems; } - QList tmp = index->estimateItems(sceneRect, Qt::SortOrder(-1), - viewTransform ? *viewTransform : QTransform()); - for (int i = 0; i < tmp.size(); ++i) - tmp.at(i)->topLevelItem()->d_ptr->itemDiscovered = 1; - - // Sort if the toplevel list is unsorted. - if (needSortTopLevelItems) { - needSortTopLevelItems = false; - qStableSort(topLevelItems.begin(), topLevelItems.end(), qt_notclosestLeaf); - } - + const QList tmp = index->estimateItems(sceneRect, Qt::SortOrder(-1), + viewTransform ? *viewTransform : QTransform()); + // estimateItems returns a list of *all* items, but we are only interested + // in the top-levels (those that are within the rect themselves and those that + // have descendants within the rect). + // ### Look into how we can add this feature to the BSP. QList tli; - for (int i = 0; i < topLevelItems.size(); ++i) { - // ### Investigate smarter ways. Looping through all top level - // items is not optimal. If the BSP tree is to have maximum - // effect, it should be possible to sort the subset of items - // quickly. We must use this approach for now, as it's the only - // current way to keep the stable sorting order (insertion order). - QGraphicsItem *item = topLevelItems.at(i); - if (item->d_ptr->itemDiscovered) { - item->d_ptr->itemDiscovered = 0; - tli << item; + for (int i = 0; i < tmp.size(); ++i) { + QGraphicsItem *topLevelItem = tmp.at(i)->topLevelItem(); + if (!topLevelItem->d_ptr->itemDiscovered) { + tli << topLevelItem; + topLevelItem->d_ptr->itemDiscovered = 1; } } + // Reset discovered bit. + for (int i = 0; i < tli.size(); ++i) + tli.at(i)->d_ptr->itemDiscovered = 0; + + qSort(tli.begin(), tli.end(), qt_notclosestLeaf); return tli; } @@ -4283,10 +4280,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * int i = 0; if (itemHasChildren) { - if (item->d_ptr->needSortChildren) { - item->d_ptr->needSortChildren = 0; - qStableSort(item->d_ptr->children.begin(), item->d_ptr->children.end(), qt_notclosestLeaf); - } + item->d_ptr->ensureSortedChildren(); if (itemClipsChildrenToShape) { painter->save(); diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 4842e72..23b0dd5 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -234,6 +234,14 @@ public: item->d_ptr->ignoreOpacity = 0; } + inline void ensureSortedTopLevelItems() + { + if (needSortTopLevelItems) { + qSort(topLevelItems.begin(), topLevelItems.end(), qt_notclosestLeaf); + needSortTopLevelItems = false; + } + } + QStyle *style; QFont font; void setFont_helper(const QFont &font); diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp index c8d755e..0688cb1 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex.cpp @@ -242,7 +242,7 @@ void QGraphicsSceneBspTreeIndexPrivate::climbTree(QGraphicsItem *item, int *stac { if (!item->d_ptr->children.isEmpty()) { QList childList = item->d_ptr->children; - qStableSort(childList.begin(), childList.end(), qt_closestLeaf); + qSort(childList.begin(), childList.end(), qt_closestLeaf); for (int i = 0; i < childList.size(); ++i) { QGraphicsItem *item = childList.at(i); if (!(item->flags() & QGraphicsItem::ItemStacksBehindParent)) @@ -281,7 +281,7 @@ void QGraphicsSceneBspTreeIndexPrivate::_q_updateSortCache() topLevels << item; } - qStableSort(topLevels.begin(), topLevels.end(), qt_closestLeaf); + qSort(topLevels.begin(), topLevels.end(), qt_closestLeaf); for (int i = 0; i < topLevels.size(); ++i) climbTree(topLevels.at(i), &stackingOrder); } @@ -446,15 +446,15 @@ void QGraphicsSceneBspTreeIndexPrivate::sortItems(QList *itemLi { if (sortCacheEnabled) { if (order == Qt::AscendingOrder) { - qStableSort(itemList->begin(), itemList->end(), closestItemFirst_withCache); + qSort(itemList->begin(), itemList->end(), closestItemFirst_withCache); } else if (order == Qt::DescendingOrder) { - qStableSort(itemList->begin(), itemList->end(), closestItemLast_withCache); + qSort(itemList->begin(), itemList->end(), closestItemLast_withCache); } } else { if (order == Qt::AscendingOrder) { - qStableSort(itemList->begin(), itemList->end(), closestItemFirst_withoutCache); + qSort(itemList->begin(), itemList->end(), closestItemFirst_withoutCache); } else if (order == Qt::DescendingOrder) { - qStableSort(itemList->begin(), itemList->end(), closestItemLast_withoutCache); + qSort(itemList->begin(), itemList->end(), closestItemLast_withoutCache); } } } diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h index 7b431e6..437b17d 100644 --- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h +++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.h @@ -173,21 +173,13 @@ inline bool qt_closestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item const QGraphicsItemPrivate *d2 = item2->d_ptr; bool f1 = d1->flags & QGraphicsItem::ItemStacksBehindParent; bool f2 = d2->flags & QGraphicsItem::ItemStacksBehindParent; - if (f1 != f2) return f2; - qreal z1 = d1->z; - qreal z2 = d2->z; - return z1 > z2; + if (f1 != f2) + return f2; + if (d1->z != d2->z) + return d1->z > d2->z; + return d1->siblingIndex > d2->siblingIndex; } -/*! - \internal -*/ -static inline bool qt_notclosestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2) -{ - return qt_closestLeaf(item2, item1); -} - - static inline bool QRectF_intersects(const QRectF &s, const QRectF &r) { qreal xp = s.left(); diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp index b317e8e..d6281e2 100644 --- a/src/gui/graphicsview/qgraphicssceneindex.cpp +++ b/src/gui/graphicsview/qgraphicssceneindex.cpp @@ -266,10 +266,7 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRe int i = 0; if (itemHasChildren) { // Sort children. - if (item->d_ptr->needSortChildren) { - item->d_ptr->needSortChildren = 0; - qStableSort(item->d_ptr->children.begin(), item->d_ptr->children.end(), qt_notclosestLeaf); - } + item->d_ptr->ensureSortedChildren(); // Clip to shape. if (itemClipsChildrenToShape) -- cgit v0.12 From 501d1395bd3fc6c67e50216345959d31c0db7707 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 2 Jul 2009 15:44:17 +0200 Subject: Revert "Add support for creating the object alongside the Data structure in QSharedPointer" This reverts commit fb51a10ee0451274a430227566ae26efb2ac4474. Sorry, it didn't work. I can fix the MSVC error, but the problem is that older GCC versions (4.2) fail with the following code: template struct Buffer { char buffer[128] __attribute__((aligned(__alignof__(T)))); }; The same works fine in GCC 4.4. --- src/corelib/tools/qsharedpointer_impl.h | 47 ----------- tests/auto/qsharedpointer/tst_qsharedpointer.cpp | 102 +---------------------- 2 files changed, 2 insertions(+), 147 deletions(-) diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h index 2fa9eb2..739a949 100644 --- a/src/corelib/tools/qsharedpointer_impl.h +++ b/src/corelib/tools/qsharedpointer_impl.h @@ -48,7 +48,6 @@ #pragma qt_sync_stop_processing #endif -#include #include #include // for qobject_cast @@ -191,34 +190,6 @@ namespace QtSharedPointer { }; template - struct ExternalRefCountWithContiguousData: public ExternalRefCountData - { -#ifdef Q_DECL_ALIGN -# ifdef Q_ALIGNOF -# define QSP_ALIGNOF(T) Q_ALIGNOF(T) -# else -# define QSP_ALIGNOF(T) (sizeof(T) >= 16 ? 16 : sizeof(T) >= 8 ? 8 : sizeof(T) >= 4 ? 4 : sizeof(T) >= 2 ? 2 : 1) -# endif - - char data[sizeof(T)] Q_DECL_ALIGN(QSP_ALIGNOF(T)); - inline T *pointer() { return reinterpret_cast(data); } - -# undef QSP_ALIGNOF -#else - union { - char data[sizeof(T) + 16]; - double dummy1; -# ifndef Q_OS_DARWIN - long double dummy2; -# endif - }; - inline T *pointer() { return reinterpret_cast(data + 16 - (quintptr(data) & 0xf)); } -#endif - - inline bool destroy() { this->pointer()->~T(); return true; } - }; - - template class ExternalRefCount: public Basic { typedef ExternalRefCountData Data; @@ -249,16 +220,6 @@ namespace QtSharedPointer { d = new ExternalRefCountWithSpecializedDeleter(ptr, deleter); } - inline void internalCreate() - { - ExternalRefCountWithContiguousData *dd = new ExternalRefCountWithContiguousData; - T *ptr = dd->pointer(); - new (ptr) T(); // create - - Basic::internalConstruct(ptr); - d = dd; - } - inline ExternalRefCount() : d(0) { } inline ~ExternalRefCount() { if (d && !deref()) delete d; } inline ExternalRefCount(const ExternalRefCount &other) : Basic(other), d(other.d) @@ -386,14 +347,6 @@ public: inline void clear() { *this = QSharedPointer(); } QWeakPointer toWeakRef() const; - -public: - static QSharedPointer create() - { - QSharedPointer result; - result.internalCreate(); - return result; - } }; template diff --git a/tests/auto/qsharedpointer/tst_qsharedpointer.cpp b/tests/auto/qsharedpointer/tst_qsharedpointer.cpp index dd53e3c..5cb435a 100644 --- a/tests/auto/qsharedpointer/tst_qsharedpointer.cpp +++ b/tests/auto/qsharedpointer/tst_qsharedpointer.cpp @@ -65,9 +65,8 @@ private slots: void dynamicCastVirtualBase(); void dynamicCastFailure(); #endif - void constCorrectness(); void customDeleter(); - void creating(); + void constCorrectness(); void validConstructs(); void invalidConstructs_data(); void invalidConstructs(); @@ -105,8 +104,6 @@ public: { delete this; } - - virtual int classLevel() { return 1; } }; int Data::generationCounter = 0; int Data::destructorCounter = 0; @@ -335,8 +332,6 @@ public: { delete this; } - - virtual int classLevel() { return 2; } }; int DerivedData::derivedDestructorCounter = 0; @@ -344,23 +339,15 @@ class Stuffing { public: char buffer[16]; - Stuffing() { for (uint i = 0; i < sizeof buffer; ++i) buffer[i] = 16 - i; } virtual ~Stuffing() { } }; class DiffPtrDerivedData: public Stuffing, public Data { -public: - virtual int classLevel() { return 3; } }; class VirtualDerived: virtual public Data { -public: - int moreData; - - VirtualDerived() : moreData(0xc0ffee) { } - virtual int classLevel() { return 4; } }; void tst_QSharedPointer::downCast() @@ -1006,82 +993,6 @@ void tst_QSharedPointer::customDeleter() QCOMPARE(derivedDataDeleter.callCount, 1); } -void tst_QSharedPointer::creating() -{ - Data::generationCounter = Data::destructorCounter = 0; - { - QSharedPointer ptr = QSharedPointer::create(); - QVERIFY(ptr.data()); - QCOMPARE(Data::generationCounter, 1); - QCOMPARE(ptr->generation, 1); - QCOMPARE(Data::destructorCounter, 0); - - QCOMPARE(ptr->classLevel(), 1); - - ptr.clear(); - QCOMPARE(Data::destructorCounter, 1); - } - - Data::generationCounter = Data::destructorCounter = 0; - { - QSharedPointer ptr = QSharedPointer::create(); - QWeakPointer weakptr = ptr; - QtSharedPointer::ExternalRefCountData *d = ptr.d; - - ptr.clear(); - QVERIFY(ptr.isNull()); - QCOMPARE(Data::destructorCounter, 1); - - // valgrind will complain here if something happened to the pointer - QVERIFY(d->weakref == 1); - QVERIFY(d->strongref == 0); - } - - Data::generationCounter = Data::destructorCounter = 0; - DerivedData::derivedDestructorCounter = 0; - { - QSharedPointer ptr = QSharedPointer::create(); - QCOMPARE(ptr->classLevel(), 2); - QCOMPARE(ptr.staticCast()->moreData, 0); - ptr.clear(); - - QCOMPARE(Data::destructorCounter, 1); - QCOMPARE(DerivedData::derivedDestructorCounter, 1); - } - - { - QSharedPointer ptr = QSharedPointer::create(); - QCOMPARE(ptr->classLevel(), 3); - QCOMPARE(ptr.staticCast()->buffer[7]+0, 16-7); - QCOMPARE(ptr.staticCast()->buffer[3]+0, 16-3); - QCOMPARE(ptr.staticCast()->buffer[0]+0, 16); - } - - { - QSharedPointer ptr = QSharedPointer::create(); - QCOMPARE(ptr->classLevel(), 4); - QCOMPARE(ptr->moreData, 0xc0ffee); - - QSharedPointer baseptr = ptr; - QCOMPARE(baseptr->classLevel(), 4); - } - - { - QSharedPointer ptr = QSharedPointer::create(); - QCOMPARE(ptr->metaObject(), &QObject::staticMetaObject); - - QPointer qptr = ptr.data(); - ptr.clear(); - - QVERIFY(qptr.isNull()); - } - - { - QSharedPointer ptr = QSharedPointer::create(); - QCOMPARE(ptr->metaObject(), &OtherObject::staticMetaObject); - } -} - void tst_QSharedPointer::validConstructs() { { @@ -1133,9 +1044,6 @@ void tst_QSharedPointer::invalidConstructs_data() << "forwardDeclaredDestructorRunCount = 0;\n" "{ QSharedPointer ptr = QSharedPointer(forwardPointer()); }\n" "exit(forwardDeclaredDestructorRunCount);"; - QTest::newRow("creating-forward-declaration") - << &QTest::QExternalTest::tryCompileFail - << "QSharedPointer::create();"; // upcast without cast operator: QTest::newRow("upcast1") @@ -1168,16 +1076,10 @@ void tst_QSharedPointer::invalidConstructs_data() << "QSharedPointer baseptr = QSharedPointer(new Data);\n" "qSharedPointerDynamicCast(baseptr);"; #endif - QTest::newRow("const-dropping-object-cast1") + QTest::newRow("const-dropping-object-cast") << &QTest::QExternalTest::tryCompileFail << "QSharedPointer baseptr = QSharedPointer(new QObject);\n" "qSharedPointerObjectCast(baseptr);"; -#ifndef QT_NO_PARTIAL_TEMPLATE_SPECIALIZATION - QTest::newRow("const-dropping-object-cast2") - << &QTest::QExternalTest::tryCompileFail - << "QSharedPointer baseptr = QSharedPointer(new QObject);\n" - "qobject_cast(baseptr);"; -#endif // arithmethics through automatic cast operators QTest::newRow("arithmethic1") -- cgit v0.12 From d9b28812d0065227e6f66817cd9bf917dfadb0f0 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 2 Jul 2009 15:49:49 +0200 Subject: Don't compile the FD_CLOEXEC-safe accept4 call if we don't know about SOCK_CLOEXEC --- src/network/socket/qnet_unix_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/socket/qnet_unix_p.h b/src/network/socket/qnet_unix_p.h index 80a4c58..ffd5b39 100644 --- a/src/network/socket/qnet_unix_p.h +++ b/src/network/socket/qnet_unix_p.h @@ -100,7 +100,7 @@ static inline int qt_safe_accept(int s, struct sockaddr *addr, QT_SOCKLEN_T *add Q_ASSERT((flags & ~O_NONBLOCK) == 0); register int fd; -#if QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC +#if QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC && defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK) // use accept4 int sockflags = SOCK_CLOEXEC; if (flags & O_NONBLOCK) -- cgit v0.12 From f30f3e7bdc846baf49ef51721a5b11d31be22cf2 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 2 Jul 2009 16:43:40 +0200 Subject: Fix build with MSVC2003: apparently the code path I thought was Unix was also older MSVC --- src/corelib/io/qtemporaryfile.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp index 2ae4611..b520bee 100644 --- a/src/corelib/io/qtemporaryfile.cpp +++ b/src/corelib/io/qtemporaryfile.cpp @@ -61,7 +61,7 @@ #include #if defined(Q_OS_UNIX) -# include "private/qcore_unix_p.h" +# include "private/qcore_unix_p.h" // overrides QT_OPEN #endif #if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) @@ -211,9 +211,9 @@ static int _gettemp(char *path, int *doopen, int domkdir, int slen) if ((*doopen = QT_OPEN(targetPath.toLocal8Bit(), O_CREAT|O_EXCL|O_RDWR # else // CE - // this is Unix + // this is Unix or older MSVC if ((*doopen = - qt_safe_open(path, QT_OPEN_CREAT|O_EXCL|QT_OPEN_RDWR +